插入排序、希尔排序、选择排序、冒泡排序

插入排序

如果有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到插入排序法,插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。
插入算法把要排序的数组分成两部分:

  • 第一部分为已排好序的,如果这个数组元素是无序的,那么这一部分最开始我们可以只认为包含一个元素。
  • 第二部分是无序的也就是待插入的。每次从无序中选择一个元素插入到有序数组里,并且保证插入后的数组也是有序的,插入一次后有序数组大小加一,无序数组大小减一,直到将无序元素全部插入位置为止。

代码实现:
第一步:i为无序数组第一个下标,把他赋值给temp;
第二步:从有序数组最后一个下标j开始,逐个和temp比较,若大于则arr[j+1]=arr[j],小于则不再进行比较;
第三步:将temp赋值到arr[j];

void InsertSort(int* arr, int n)//插入排序
{
	int i = 0;//i是无序数组下标
	int j = 0;//j是有序数组下标
	for (i = 1; i <= n - 1; i++)
	{
		int temp = arr[i];//第一个无序数组下标
		for (j = i - 1; j >= 0; j--)
		{
			if (temp < arr[j])
			{
				arr[j + 1] = arr[j];//从最后一个元素比较,若小的话往后移动移位
			}
			else
				break;
		}
		//因为最后一次j--了,但是没有移动
		//所以这里j要加一
		arr[j + 1] = temp;
	}
}

希尔排序

希尔排序是建立在插入排序的基础上,通过按照一定的下标增量分组,对每组实行插入排序。随着增量减小直到1就为一个插入排序。希尔排序之所以能提高插入排序的效率,在于

  1. 分组后进行插入排序,如果发生交换,每次数据移动的比较大,比插入排序一次移动一位的效率高。
  2. 通过前面分组的插入排序,能使数组整体有序性升高,而插入排序对于有序数组的时间复杂度为o(n)。

希尔排序需要自己设置增量参数,经过前人测试,认为设置素数比较好,只要最后的增量为1就可以。
代码实现:
内部循环和插入排序基本相同唯一不同的是多了外面一层循环,用来减小增量。
注意,采用希尔排序的时候不是一组完了再一组进行插入排序,而是每组逐个进行一次插入排序

void ShellSort(int* arr, int n)//希尔排序
{
	int tag = n;
	int i = 0;
	int j = 0;
	while (tag>1)
	{
		tag = tag / 3 + 1;
		for (i = 0; i <= n - 1; i++)
		{
			int* temp = &arr[i];
			for (j = i + tag; j <= n - 1; j += tag)
			{
				if (*temp > arr[j])
				{
					Swap(temp, &arr[j]);
					temp = &arr[j];
				}
				else
					break;
			}	
		}
	}
}

选择排序

第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。由于是每次都要遍历整个数组,所以选择排序的时间复杂度始终是o(n^2)。
代码实现:
从数组两边同时找元素,遇到大的和数组最头元素交换,遇到最小的放到数组最尾元素交换,然后缩小数组继续,直至数组大小为1。

void SelectSort(int* arr, int n)//选择排序
{
	int begin = 0;
	int end = n - 1;
	int index = 0;
	int rear = 0;
	while (begin<=end)
	{
		for (index = begin; index<=end; index++)
		{
			if (arr[begin] > arr[index])
				Swap(&arr[begin], &arr[index]);
		}
		for (index = begin; index <= end; index++)
		{
			if (arr[end] < arr[index])
				Swap(&arr[end], &arr[index]);
		}
		begin++;
		end--;
	}
}

冒泡排序

设置两个相邻指针,遍历整个数组,每次两个相邻元素进行比较,若升序,如果前大于后则交换,每次遍历一次后都能保证将最大元素排到数组最后,然后从尾部缩小数组范围,再次进行,又将次最大元素放到最后,以此循环,最后得到有序数组。
冒泡排序因为要遍历n次数组,第一次遍历n个元素,第二次n-1个元素,第i次遍历n-i次元素,所以它的时间复杂度为o(n^2)。
代码实现:
j用来缩小数组,i用来遍历数组

void BubbleSort(int* arr, int n)
{

	for (size_t j = n-1; j > 0; j--)
	{
		for (size_t i = 0; i < j; i++)
		{
			if (arr[i]>arr[i + 1])
			{
				Swap(&arr[i], &arr[i + 1]);
			}
		}
	}
}
发布了35 篇原创文章 · 获赞 13 · 访问量 2113

猜你喜欢

转载自blog.csdn.net/weixin_42458272/article/details/97400904