学习 严蔚敏讲数据结构笔记24
2013-05-29 07:43
330 查看
三、希尔排序(又称缩小增量排序)
基本思想:对带排序记录序列先作“宏观”调整,再作“围观”调整。
所谓“宏观”调整,置的是“跳跃式”的插入排序。
具体做法为:
将记录序列分成若干子序列,分别对每个子序列进行插入排序。
例如:将n个记录分成d个序列:
{R[1],R[1+d],R[1+2d],…,R[1+kd]}
{R[2],R[1+d],R[2+d],…,R[2+kd]}
…
{R[d],R[2d],R[3d],…R[kd],R[(k+1)d]}
其中,d称为增量,它的值在排序过程中从大到小逐渐缩小,直至最后一趟排序减为1.
例如
16,25,12,31,47,11,23,36,9,18,31
42_002 |
void ShellInsert(Elem R[], int dk) { for(i = dk+1; i <= n; ++i) { if(R[i].key < R[i-dk].key) { R[0] = R[i]; //暂存在R[0] for(j = i-kd; i > 0 && (R[j].key); j -= dk) R[j+dk] = R[j]; //记录后移,查找插入位置 R[j+dk] = R[0]; //插入 }//if } } void ShellSort(Elem R[], int dlta[], int t) { //增量为dlta[]的希尔排序 for(k = 0; k < t; ++ t) ShellInsert(R, dlta[k]); //一趟增量为dlta[k]的插入排序 }//ShellSort |
10.3快速排序
一、起泡排序
二、一趟快速排序
三、快速排序
四、快速排序的时间分析
一、假设在排序过程中,记录序列R[1,…,n]的状态为:
42_003 |
void BubbleSort(Elem R[], int n) { i = n; while(i > 1) { lastExchangeIndex = 1; for(j = 1; j < i; j ++) if(A[j+1] < A[j]) { Swap(A[j], A[j+1]); lastExchangeIndex = j; }//if i = lastExchangeIndex; }//while }//BubbleSort |
时间分析:最好的情况(关键字在序列中顺序有序):只需进行一趟起泡
最坏的情况(关键字在记录序列中逆序有序):需进行n-1趟起泡
二、一趟快速排序
目标:找一个记录,以它的关键字作为“枢轴”,凡其关键字小于枢轴的记录均移动至该记录之前,反之,凡关键字大于枢轴的记录均移动至该记录之后,致使一趟排序之后,记录的无序序列R[s,..,t]将分割成两部分:R[s,…i-1]和R[i+1,…t],且R[j].key<=R[i].key<=R[j].key,(s<=j<=i-1)枢轴(i+1<=j<=t)
例如:关键字序列
52,49,80,36,14,58,61,97,23,75
调整为:23,49,14,36,(52),58,61,97,80,75
其中(52)为枢轴,在调整过程中,需设立两个指针:low和high,它们的初始值分别为:s和t,之后逐渐减小high,增加low,并保证R[high].key>=52,而R[low].key<=52,否则进行记录的“交换”。
42_004 |
int Partition(Elem R[], int low, int high) { R[0] = R[low]; pivotkey = R[low].key; //枢轴记录关键字 while(low < high) { while(low < high && R[high].key >= pivotkey) -- high; R[low] = R[high]; while(low < high && R[low].key <= pivotkey) ++ low; R[high] = R[low]; } R[low] = R[0]; //枢轴记录到位 return low; }//Partition |
42_005 |
void QSort(Elem R[], int low, int high) { //对记录序列R[low,...,high]进行快速排序 if(low < high - 1) { //长度大于1 pivotloc = Partition(L, low, high); //将L...r[low,...,high]一分为二 QSort(L, low, pivotloc - 1); //对低子表递归排序,pivotloc是枢轴位置 QSort(L,pivotloc + 1, high); //对高子表递归排序 } }//QSort void QuickSort(Elem R[], int n) { //对记录序列进行快速排序 QSort(R, l, n); }//QuickSort |
假设依次划分所得枢轴位置i=k,则对n个记录进行快速排序所需时间
对n个记录进行一次划分所需时间,若带排序列中记录的关键字是随机分布的,则k取1至n中任意一值的可能性相同,由此可得快速排序所需时间的平均值为:
快速排序的时间复杂度为O(nlogn)
若带排序的即初始状态按关键字有序时,快速排序将蜕化为起泡排序,其时间复杂度为O(n2)。
为避免出现这种情况,需在进行快速排序之前,进行“预处理”,即:比较R[s].key, R[t].key, R[(s+t)/2].key去下届对应的key,然后取关键字为“三者之中”的记录为枢轴记录。
10.4堆排序(选择类排序)
简单选择排序
堆排序
一、简单选择排序
假设排序过程中,带排序记录序列的状态为:
简单选择排序的算法描述如下:
42_006 |
void SelectSort(Elem R[], int n) { //对记录序列R[1,...,n]做简单选择排序 for(i = 1; i < n; ++ i) { //选择第i小的记录,并交换到位 j = SelectMinKey(R, i); //在R[i,...n]中选择最小的记录 if(i != j) R[i] <-- --> R[j]; //与第i个记录交换 } } |
对n个记录进行简单选择排序,所需进行的关键字间的比较次数总计为
移动记录的次数,最小值为0,最大值为3(n-1)
二、堆排序
堆的定义:
堆是满足下列性质的数列{r1,r2,…,rn}
R1是最小的,称为小顶堆
堆排序即是利用堆的特性对记录序列进行排序的一种排序方法。
例如:
{40,55,49,73,12,27,98,81,64,36}
所谓“筛选”指的是,对一棵左/右子树均为堆的完全二叉树,“调整”根结点使整个二叉树为堆。
43_001 |
void HeapSort(Elem R[], int n) { //对记录序列R[1,...,n]进行堆排序 for(i = n/2; i > 0; -- i) HeapAdjust(R, i, n); //建大顶堆 for(i = n; i > 1; -- i) R[1] <-- -->R[i]; //将堆顶记录和当前未经排序子序列 R[1,...i]中最后一个记录相互交换 HeapAdjust(R, 1, i - 1); //对R[1]进行筛选 } void HeapAdjust(Elem R[], int s, int m) { re = R[s]; for(j = 2 * s; j <= m; j *= 2) { if(j < m && R[i].key < R[j+1].key) ++ j; //j为key较大的记录的下标 if(rc.key >= R[j].key) break; //rc应插入在位置s上 R[s] = R[j]; s = j; } R[s] = rc; //插入 } |
1. 对深度为k的堆,“筛选”所需进行的关键字比较的次数至多为2(k-1)。
2. 对n个关键字,建成深度为h=([log2n]+1)堆,所需进行的关键字比较的次数至多4n;
3. 调整“堆顶”n-1次,总共进行的关键字比较的次数不超过
因此,堆排序的时间复杂度为O(nlogn);
相关文章推荐
- 严蔚敏数据结构学习笔记二.线性表
- 学习 严蔚敏讲数据结构笔记15
- 文件归并学习 严蔚敏讲数据结构笔记26
- 严蔚敏数据结构学习笔记四.串
- 学习 严蔚敏讲数据结构笔记06
- 学习 严蔚敏讲数据结构笔记16
- 严蔚敏数据结构学习笔记六.树和二叉树
- 学习 严蔚敏讲数据结构笔记07
- 学习 严蔚敏讲数据结构笔记17
- 数据结构学习笔记 图:深度优先搜索(严蔚敏版)
- 严蔚敏版数据结构学习笔记(4):队列
- 学习 严蔚敏讲数据结构笔记08
- 学习 严蔚敏讲数据结构笔记18
- 学习 严蔚敏讲数据结构笔记01
- 学习 严蔚敏讲数据结构笔记09
- 学习 严蔚敏讲数据结构笔记19
- 学习 严蔚敏讲数据结构笔记10
- 学习 严蔚敏讲数据结构笔记20
- 学习 严蔚敏讲数据结构笔记02
- 学习 严蔚敏讲数据结构笔记03