/*
*希尔排序
*/
希尔排序属于内部排序中的插入排序,它是不稳定的排序,时间复杂度为O(n2/3)n的2/3次幂,具体的算法步骤不再赘述,看图说话
比如有一串数字为:9,13,8,2,5,13,7,1,15,11
d1=[10/2]=5 d2=[5/2]=3 d3=[3/2]=1 第一趟五五分,第二趟三三分,第三趟增量必须为1
第一趟排序结果为9,7,1,2,5,13,13,8,15,11
第二趟排序结果:2 5 1 9 7 13 11 8 15 13
第三趟:1 2 5 7 8 9 11 13 13 15
/*
*快速排序
*/
先看一看C程序代码
/* 快 速 排 序 */
#include "stdio.h"
void QuickSort(int e[], int first, int end)
{
int i=first,j=end,temp=e[first];
while(i<j)
{
while(i<j && e[j]>=temp)
j--;
e[i]=e[j];
while(i<j && e[i]<=temp)
i++;
e[j]=e[i];
}
e[i]=temp;
if(first<i-1)
QuickSort(e,first,i-1);
if(end>i+1)
QuickSort(e,i+1,end);
}
void main()
{
int arr[] = {49, 38, 65, 97, 76, 13, 27, 49};
int len = 8;
int i;
printf("before sort\n");
for(i=0; i<len; i++)
printf("%d ", arr[i]);
printf("\n");
QuickSort(arr, 0, len-1);
printf("after sorted\n");
for(i=0; i<len; i++)
printf("%d ", arr[i]);
printf("\n");
}
首先介绍一下思想:
1.设置两个变量I、J,排序开始的时候I:=1,J:=N;
2.以第一个数组元素作为关键数据,赋值给X,即X:=A[1];
3.从J开始向前搜索,即由后开始向前搜索(J:=J-1),找到第一个小于X的值,两者交换;
4.从I开始向后搜索,即由前开始向后搜索(I:=I+1),找到第一个大于X的值,两者交换;
5.重复第3、4步,直到I=J;
实战:比如使用快速排序下列一串数组:49 38 65 97 76 13 27
49 38 65 97 76 13 27
i j
j对应的元素比i对应的元素小,所以交换,j不变,i后移
27 38 65 97 76 13 49
i j
i小于j,不能交换,i继续后移
27 38 49 97 76 13 65
i j
i大于j,交换,此时此刻j前移,i不变
27 38 49 97 76 13 65
i j
j小于i,交换,j不变,i后移
27 38 13 97 76 49 65
i j
i大于j,交换,i不变,j前移
27 38 13 49 76 97 65
i j
i小于j,i继续后移与j重合,第一趟排序结束,所以排序结果为
27 38 13 49 76 97 65
保证了49前面的元素都比49小,而49后面的元素都比49大
接下来对49前面的元素和后面的元素分别再次进行快速排序,{13} 27 {38} 49 {65} 76 {97}
快速排序就是利用栈的递归方法,分治思想,栈的最大深度为log2n取值下限+1在所有同数量级(O(nlogn))的排序方法中,其平均性能最好,若初始记录基本有序,快排将蜕化为冒泡排序,时间复杂度为O(n²),
接下来我要讲一讲我认为最复杂的一种排序——堆排序
/*
*堆排序(Heap Sort)
*/
首先介绍一下小根堆和大根堆
小根堆:每个节点小于等于左、右孩子,且根节点是序列n个元素的最小值
大根堆:每个节点大于等于左、右孩子,且根节点是序列n个元素的最大值
小根堆
性质:
1.堆是一棵采用顺序存储结构的完全二叉树,k是根节点
2.分为大(小)根堆
3.按元素值非递减排序
4.堆中任一子树也为堆
小根堆排序后得到的是非递减序列
大根堆排序后得到非递增序列
堆排序的时间复杂度为O(N*logN)
下面我们来看看堆的建立、插入元素、删除元素的具体操作
堆的建立:
记住建立过程永远是从上到下,从左到右的顺序,先来热个身
初始化序列表为{3,1,4}
将1 与3进行替换后实现了堆的建立结果:
下面给出以下序列,我将详细讲解如何建立一个小根堆
{49,38,65,97,76,13,27,49}
将此序列看成是一棵完全二叉树,最后一个非终端结点是n/2取值下限个元素,那么筛选就从这个元素开始,如图则从第4个元素97开始筛选,97>49,交换
接下来从第三个元素65开始:13<65,交换
第二个元素为38,不需要调整,第一个元素为49,49<13,交换
再次进行调整得到了小根堆,这就是堆的建立
堆的元素插入:
如果插入2
2与3进行替换得到最终结果为
如果初始插入的是0,将进行两次交换,则最终结果为
堆的元素删除:
如果删除根节点,将以堆中最后一个元素替代之,此时根节点左、右子树均为堆,则仅需自上至下进行调整即可,
堆排序定义:若在输出堆顶的最小值后,使得n-1个元素的序列又建成一个堆,则得到n个元素中的次小值,如此反复执行,便能得到一个有序序列,这个过程称之为堆排序
假如有以下小根堆:
97是最后一个元素,与13进行替换,取出13,
此时27为堆里最小的元素,将27与堆的最后一个元素进行交换,取出27,{13,27} ,此时97为最后一个元素,代替27
调整后
这种方法叫筛选法,
然后取出38,{13,27,38} 65到根节点进行调整,随后筛选出49,49,65,76,97,这就是堆排序
堆排序适合n较大的文件,深度为k的堆,筛选法关键字比较次数为2(k-1),堆排序在最坏情况下时间复杂度为0(nlogn),相比于快排,这是堆排序最大的优点