基本排序算法总结

准备找工作了,开始看数据结构。看到了排序算法,写个基本的算法原理与总结,方便查看。

前提:数组sque[N]; ,排序结果为小元素在前,大元素在后。

1.冒泡排序

算法思想:不断通过相邻元素两两比较,并进行多次交换,来对数组的元素进行排序。

对于当前元素位置i,从尾部n向i方向开始进行相邻的两两比较,当坐标大于右边时进行交换,否则跳过(continue)。结束后i+1并继续循环。

属于稳定排序,时间复杂度O(n^2)

void BobSort(int L[], int n)
{

	for (int i = 0; i < n;i++)
	{
		for (int j = n - 1; j>i;j--)  //从后向前遍历,将小的元素往小坐标靠
		{
			if (L[j - 1] > L[j])
			{
				swap(L[j],L[j - 1] );
			}
		}
	}
}
与暴力法1的方式相比,要快一点,但是还是不够快,有改进的方法,这里没写出。

2选择排序;

思想:对于当前数据,找到后面剩下的里最小的,然后进行交换;继续循环下去;

属于稳定排序,算法时间复杂度O(n^2)

代码://待补充

3.直接插入排序

算法思想:依次检查相邻两两元素,若出现左边大于右边的情况;将此较小的元素复制到0位置,然后从当前位置的前一个位置开始,向左循环,不停的检查,如果定位到的元素大于0位的元素,向前移动移位。最后到达0位时不满足大于的条件,停止;然后i+1的位置为0位位置的值。相当于把最后一次移走的元素的位置填上0位的值;循环;
算法属于稳定排序,算法时间复杂度为O(n^2);
代码://待补充

该进型排序:算法复杂度要小于n^2,但是会导致不稳定排序,需要额外的空间进行存储,包含希尔排序;堆排序;归并排序与快速排序法;

4.希尔排序:

前提得是数据基本有序,基本上大的在后面,小的在前面

算法思想:产生一个随机增量,然后对间隔某个增量的子序列进行大小交换,等基于此增量的比较结束后,再次减小此增量,继续循环进行交换,直到此增量的值为1,交换完毕后结束。

算法时间复杂度O( n^(3/2)),  为不稳定排序;

代码://待补充

5.堆排序

基于一种堆的结构:即根节点的元素的值要么大于子节点,要么小于子节点的值的完全二叉树结构;与二叉排序树不同。因此包含大顶堆与小顶堆。
完全二叉树,即按照满二叉树的方式生成,所有的叶子节点都在一层,非叶子层的节点可以没有子节点。因此其节点的编号按照生成的方式进行排列;往往具有一下性质:父节点若为n,其子节点为2n+1与2n+2;对于子节点而言,其父节点为[i/2](向零取整)。
排序算法中往往采用大顶堆的生成方式。基本思想是:对一堆数据,首先按照大顶堆的生成方式对数组中的元素进行变换,此时,数组第一个元素即为最大元素,然后将其与最后一个元素进行交换。接下来将除最大元以外的元素重新以大顶堆的生成方式进行排序并交换;循环;

算法时间复杂度:循环n次,每次创建的大顶堆的复杂度为log(n),因此为O(nlog(n)),为不稳定排序;

代码:

堆排序
void HeapSort(int *L,int n)  //主函数
{
	int i;
	for (i = n / 2; i >= 0; i--)
	{
		HeapAdjast(L, i, n);  //对子节点到根节点逐步生成大顶堆
	}
	for (i = n; i > 1;i--)
	{
		swap(L[1], L[i]); //将最大元素与末端交换
		HeapAdjast(L, 1, i - 1);  //重新生成大顶堆
	}
}


void HeapAdjast(int *L, int s, int m)  //大顶底生成算法
{
	int temp, j;
	temp = L[s];
	for (j = 2 * s; j < m;j*=2)  //将当前节点的值与合适位置的点进行交换
	{
		if (j < m&&L[j] < L[j + 1])  j++;
		if (temp>=L[j]) break;
		L[s] = L[j];
		s = j;
		
	}
	L[s] = temp;
}


6.归并排序法 

基本思想:采用递归的方式,对待排序的序列,将其按照下标的平均值分成两份,然后对左右子序列分别进行递归排序操作,当对此左右子序列完成排序后,进行合并操作,由两个待排序的子序列得到排序好的一个更长的序列。

递归时的停止条件就是判断每个要排序的子序列的起始与结尾的索引号是否相等,即此序列只有一个元素了。此时将此值存到目标数组并返回。

算法复杂度:O(nlog(n)),为稳定排序

7.快速排序法 

基本思想:也是采用递归的思想,对于一个待排序的子序列,首先获取此序列的一个元素,然后将此元素作为枢轴,移动到序列中合适的位置,即左边的元素比它小,右边的元素比它大。此时由此枢轴进行划分的两个子序列已经左右有序了,但是其内部还是无序的,因此调用递归,对由此枢轴划分得到的左右子序列分别进行排序。递归的停止条件就是序列的开始索引要小于结束索引。一旦等两个索引相等了那就停止了。此外还有针对枢轴旋转的改进。

平均算法复杂度:O(nlog(n)) ,也是属于不稳定排序。不过从所有的排序来看,在面对大量的元素时,快速排序的性能最好,STL中的sort也是基于快速排序进行实现的。

快排的考试频率太高了,不会不行啊,上代码。同时网上的版本很多,因此要找到一个合适自己理解的版本,这个参考大话数据结构那本书的,代码条例清楚,比较容易懂。

void MyquickSort(int L[],int n)  //此函数为代码的主函数,注意数组的下标是从1开始的。0位置的元素可以为0
{
	quickSOrt(L, 1, n);
}

void quickSOrt(int L[], int m, int n)  //实际进行排序的递归函数
{
	int key;
	if (m<n)
	{
		key = GetLey(L, m, n);//寻找key,并在key的基础上,对数据两边的元素进行小于key的在左边                                      //,大于key的在右边
		quickSOrt(L, m, key - 1);//对key左边的进行排序,
		quickSOrt(L, key + 1, n);//对key右边的进行排序
	}
}

int GetLey(int L[], int m, int n)
{
	int key = L[m];//将做小的下标对应值作为key,其实也是改进的出发点

	while (m<n)  //从两边交替扫描
	{
		while (m<n&&L[n] >= key){ n--; }
		swap(L[m], L[n]);
		while (m<n&&L[m]<=key){ m++; }
		swap(L[m], L[n]);
	}
	return m;//这里一定要返回的是小下标,而不是key
}






参考资料:

1、《大话数据结构》。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值