【朝花夕拾之排序算法总结】 快速排序,堆排序总结

大二学的数据结构,现在回想起来还是有很多混淆的地方。在这里总结一下,简单的冒泡,插入,选择我这里不再赘述。

一、快速排序

我的理解(不对的地方欢迎指正,共同学习哈O(∩_∩)O):

快速排序的思想就是先选一个元素作为“轴”,升序排序的话,每一次将一个比轴小的元素移动到轴的左边和一个比轴大的移动到轴的右边。假如有这么10个数字等待排序 8,0,3,7,9,5,6,1,4,2 那么可以选第1个元素(下标为0的元素闲置不用)作为轴。那么这一次要做的就是:

1、从最右边(也就是第10个元素)开始往回找,找出一个比 8 小的元素,于是找到了2。于是直接将2与8交换位置变成 :2,0,3,7,9,5,6,1,4,8;

2、从刚刚8的下标开始(也就是最左边),找出一个比8大的数。于是找到了9,与8交换变成:2,0,3,7,8,5,6,1,4,9

3、从9的下标开始往回找一个比8小的数,找到了4。与8交换变成2,0,3,7,4,5,6,1,8,9

到了这里可以看到在轴(8)的左边,全都是比8小的数,在8的右边,全都是比8大的数。这就是一趟快排的调整。接下来只需要将轴的两边递归即可得出排序结果。

代码的实现跟上面的略有不同,就是轴每次都要与其他元素交换。我们其实可以发现轴的最终位置就是每一趟快排的调整最后移动的元素的位置。

所以可先将轴暂存起来,交换改为直接赋值,最后在将轴赋值给每一趟快排的调整最后移动的元素的位置即可。C语言代码实现如下:

//快速排序的调整函数
int QuickAdjust(int *array,int low,int high){
 int temp = array[low];//本次排序的轴元素
 while(low < high){
  //找出第一个比轴小的数
  while(low < high && array[high] > temp) --high;
  array[low] = array[high];
  //找出第一个比轴大的数
  while(low < high && array[low] < temp) ++low;
  array[high] = array[low];
 }
 array[low] = temp;
 return low;
}
//快速排序
void QuickSort(int *array,int low,int high){
	if(low < high){
	 int prov = QuickAdjust(array,low,high);
     QuickSort(array,low,prov - 1);
	 QuickSort(array,prov + 1,high);
	}
}

二、堆排序

堆排序借助的是完全二叉树的顺序存储结构的特点进行循环调整的一种排序算法。

比如 8,0,3,7,9,5,6,1,4,2存储一棵完全二叉树(下标从1开始),那么这棵二叉树的我们可以很容易画出来:


可以看出每一个节点的左子树下标就是这个节点的下标乘以2。这样我们便可以很方便地将这棵树进行调整。

升序排序的话是循环调整成为大顶堆(根节点比子树大的完全二叉树),堆排序的思想是首先将整个堆调整成为大顶堆,调整方法如下:

1、设有n个节点,选取第n/2个节点也就是9(最后一个具备子树的节点 ),9的子树中最大的节点的值若是比9的值大,那么将9与其子树中最大的节点互换;

2、然后按此法调整K之前的节点(显然都是具备子树的节点),每次只需判断直接的左右孩子即可,但是替换之后需调整替换之后的子树。比如在调整 0这个节点的时候,可以看到0的两个子树均是大顶堆,将子树中大的与0比较,因为9 > 0,所以互换。互换之后需要判断 换后的0 的子树,因为2>0,所以还是要继续将0与2互换。

上图调整之后会变成:


之后循环将根节点(也就是最上面的那个节点)与最后一个节点互换,互换之后,最后一个节点在以后的堆调整都不算在堆里面(因为这个已经是最大的数了)。相当于循环取出最大的数。C语言的实现如下:

//堆排序的调整函数,将节点s调整为大顶堆
void HeapAdjust(int *array,int s,int m){
 int a = 2*s,temp = array[s];
 while(a <= m){
  if(a < m && array[a] < array[a+1]) ++a; //取左右子树中最大的
  //若比根节点小,说明不用调换
  if(array[a] < temp) break;
  //调换位置调整成大顶堆
  array[s] = array[a];
  s = a; //继续调整子树成为大顶堆
  a *= 2;
 }
 array[s] = temp;
}
//对数组array进行堆排,len为该数组长度 
void HeapSort(int *array,int len){
 int i,temp;
 for(i = len/2;i > 0; --i)
     HeapAdjust(array,i,len);
 for(i = len;i > 1; --i){
         temp = array[1];
	 array[1] = array[i];
     array[i] = temp;
     HeapAdjust(array,1,i-1);
 }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值