几种常见的排序

排序

  排序:排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作,在生活中排序的运用又很多,如某宝的商品排名,院校排名等。

  常见的排序分为:插入排序、选择排序、交换排序、归并排序等,其中插入排序包含直接插入排序与希尔排序,选择排序包含:选择排序、堆排序,交换排序包括:冒泡排序、快速排序,归并排序包含其本身。

  本次主要介绍插入排序与选择排序中的堆排序,插入排序的思路比较简单,其基本思想就像平时打扑克牌一样,将无序的牌从大到小或从小到大逐个插入有序的扑克牌中,直到所有的牌有序,更详细的描述如下:当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移。
  其主要代码如下所示:

void InserSort(int* a, int n)
{
	
	for (int i = 0;i < n-1;++i)
	{
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (a[end] > tmp)
			{
				a[end + 1] = a[end];
				--end;
			}
			else
			{
				break;
			}
		}
		a[end + 1] = tmp;
	}

}

  先理解while里面的内容,相当于单趟插入排序,假设end位置为3,则从数组的第三个数作为开始,从end向数组下标为0的位置逐次靠近,若a[end]>a[end+1]的话,将end位置的数往后挪一个,再将end–,就是逐次靠近数组下标为0的过程,直到前end的个数有序,而for语句的过程相当于控制前n个数有序的过程,这就是直接插入的过程,但是直接插入在时间复杂度上表现为O(N^2),因为在数组最坏的情况(数组为逆序,此时需要排升序),故针对此情况,希尔提出了一种改进直接插入排序的方法,即希尔排序。
  希尔排序的过程由预排序到直接排序的过程,在预排序的过程中,使用间隔空间排序的方法,使用gap来表示整个间隔的大小,其预排序的思路与直接插入排序一致,不同的是,直接插入排序是将两个相邻的数进行比较,然后将较大者往后挪(在排升序的情况下,降序相反),而预排序的过程是间隔gap的两个数进行比较,较大者往后挪,当gap为1时,其就是直接插入排序,gap值越大,越大的数越快的到达尾端(在升序的情况下),但其越不接近有序,gap越小,其越接近有序,但较大的数越慢到达尾端,下图显示了不同gap值下,数组排序的不同状态。
不同gap显示的过程  希尔排序的代码如下:

void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		for (int i = 0;i < n - gap;++i)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (a[end] > tmp)
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}

}

  希尔排序通过gap来控制预排序的过程,当gap值为1时,排序为直接插入排序,最终完成对数组的排序,希尔排序的时间复杂度在O(n^1.5)左右,其时间复杂度计算较为繁琐,这里就不展开讨论,后续继续分享其他几种排序的思路,并讨论其时间复杂度,与稳定性。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值