《数据结构》王道 第八章 排序
1. 排序的基本概念
1.1 算法的评价指标
2. 插入排序
2.1 算法实现
2.2 算法效率分析
2.3 优化
2.4 对链表进行插入排序
3. 希尔排序(shell sort)
元素个数除以2等于4.
还有其他分割方式,就是每一趟分割的距离不一样,但是分割完的每个子表都是进行直接插入排序。
3.1 算法实现
另一种方法(比较符合上面的例子):
void ShellSort(int array[], int n)
{
int i, j, step;
for (step = n / 2; step > 0; step = step / 2) //这里的step步长是根据10个元素这种情况定义的
{
for (i = 0; i < step; i++) //i是子数组的编号
{
for (j = i + step; j < n; j = j + step) //数组下标j,数组步长下标j+step
{
if (array[j] < array[j - step])
{
int temp = array[j]; //把数组下标j的值放到temp中
int k = j - step;
while (k >= 0 && temp < array[k])
{
array[k + step] = array[k]; //把大的值往后插入
k = k - step;
}
array[k + step] = temp; //把小的值往前插入
}
}
}
}
}
3.2 算法性能分析
4. 交换排序
4.1 冒泡排序
依次进行:
4.1.1 算法实现
4.1.2 算法性能分析
4.2 快速排序(常考,代码最好会写)
举个例子:
这里我们选第一个元素作为枢轴。
一开始是从high从后往前搜索比枢轴小的元素,并移动到左边,即low所指的位置。
当把右边的一个元素移动前面后,high的位置就空出来了,所以从low开始从前往后查找比枢轴大的元素移动high的位置,即移到右边。每次都这样循环进行下去,直到把比枢轴小的元素都移到枢轴的左边,比枢轴大于或等于的元素都移到枢轴的右边为止。
接下来对枢轴左边继续一样的处理,此时重新选取左边的第一个元素作为枢轴(每一次都得重新选择枢轴):
当low==high时,枢轴位置就确定了。
接下来对一开始的枢轴(49)的右边进行同样的操作。
以此类推:
最后排完序是这样的:
4.2.1 算法实现
4.2.2 算法性能分析
5. 选择排序
5.1 简单选择排序
5.1.1 算法实现
5.1.2 算法性能分析
5.2 堆排序
5.2.1 堆的概念
5.2.2 基于堆进行排序
我们以大根堆为例,按照步骤来:
1. 建立大根堆
所以最后建成的大根堆是这样子的:
2. 代码实现
我们直接看当进行到调整根结点的情况:
3. 基于大根堆进行排序
依次执行下去,直到剩下最后一个元素:
4. 基于大根堆排序的代码
5. 算法效率分析
6. 稳定性
5.3 堆的插入删除
对比关键字次数的常考的考点。
5.3.1 插入
5.3.2 删除
6. 归并排序(Merge Sort)
6.1 算法实现
6.2 算法效率分析
7. 基数排序
每一趟都是先分配再收集。
从个位开始分配:
收集是从个位比较大的开始收集。因为我们是要形成一个递减序列。
7.1 概念
7.2 算法效率分析
7.3 稳定性
7.4 应用
8. 外部排序
8.1 外存和内存之间的数据交换
8.2 外部排序原理
8.2.1 构造初始归并段
这样就完成了一个归并段的初始化,接下来以此类推:
8.2.2 第一趟归并
第一趟归并结束。
8.2.3 第二趟归并
依次进行下去,得到:
第二趟结束。
8.2.4 第三趟排序
8.3 时间开销分析
8.4 优化:多路归并
初始归并段已经完成了。
8.5 优化:减少初始归并段数量(即r减小)
8.6 什么是多路平衡归并
9. 败者树
派大星只需要在自己在一边一路打上去就行了。
9.1 应用
9.2 实现思路
10. 置换-选择排序(减少初始归并段的数量)
继续进行下去:
11. 最佳归并树
11.1 归并树的性质
11.2 多路归并的最佳归并树