voidBinaryInsertSorter(Record Array[], int n){ Record TempRecord; int left, right, middle; for (int i = 1; i < n; i++) { // 依次插入第 i 个记录 TempRecord = Array[i]; // 保存当前待插入记录 left = 0; right = i - 1; // 记录已排好序序列的左右位置 while (left <= right) { middle = (left + right) / 2; if (TempRecord < Array[middle]) right = middle - 1; else left = middle + 1; } for (int j = i - 1; j >= left; j--) // 记录后移 Array[j + 1] = Array[j]; Array[left] = TempRecord; // 插入 left 指针位置 } }
冒泡
算法稳定
直接选择排序
cpp
voidStraightSelectSorter(Record Array[], int n){ // 依次选出第 i 小的记录,即剩余记录中最小的那个 for (int i = 0; i < n - 1; i++) { int Smallest = i; // 首先假设记录 i 就是最小的 for (int j = i + 1; j < n; j++) // 开始向后扫描所有剩余记录 if (Array[j] < Array[Smallest]) Smallest = j; // 如发现更小记录,记录其位置 swap(Array, i, Smallest); // 将第 i 小的记录放在第 i 个位置 } }
== 注意 ==:不稳定!
shell 排序
shell 排序的提出基于直接插入排序的两个性质
在待排序序列较短情形下效率高
在整体有序的情形下时间代价低
shell 排序又称为 “缩小增量排序”
不稳定的排序方法
cpp
// Shell 排序实现,delta=2 voidShellSorter(Record Array[], int n){ for (int delta = n / 2; delta > 0; delta /= 2) { // 分别对 delta 个子序列排序 for (int j = 0; j < delta; j++) ModifiedInsertSort(&Array[j], n - j, delta); } } voidModifiedInsertSort(Record Array[], int n, int delta){ // 对子序列中第一个记录排序 for (int i = delta; i < n; i += delta) { for (int j = i; j >= delta; j -= delta) { if (Array[j] < Array[j - delta]) swap(Array, j, j - delta); else break; } } }
基于分治法的排序
快速排序
cpp
#include<iostream> usingnamespace std;
// 定义Record结构体 structRecord { int key; // 可以根据需要添加其他字段 };
template <classRecord> voidMerge(Record Array[], Record TempArray[], int left, int right, int middle){ int i, j, index1, index2; for (j = left; j <= right; j++) // 将数组暂存入临时数组 TempArray[j] = Array[j];
while (index1 <= middle) // 只剩左序列,可以直接复制 Array[i++] = TempArray[index1++];
while (index2 <= right) // 只剩右序列,可以直接复制 Array[i++] = TempArray[index2++]; }
堆排序
分配排序
桶排序
cpp
//统计每个取值出现的次数 for (i=0;i<n;i++) count[Array[i]]++; //统计小于等于i的元素个数 for (i=1;i<max;i++) count[i]=count[i-1]+count [i]; //按顺序输出有序序列 for (i=n-1;i>=0;i--) Array[--count[TempArray[i]]] = TempArray[i];
实现
cpp
#include<iostream> usingnamespace std;
// ...existing code... voidBucketSort(int *array, int n, int m){ // 初始化临时数组 int temparray[n] = {0}; // 将原数组复制到临时数组 for (int i = 0; i < n; i++){ temparray[i] = array[i]; }
// 初始化计数数组 int count[m] = {0}; // 统计每个元素的出现次数 for (int i = 0; i < n; i++){ count[array[i]]++; } // 计算累计计数 for (int i = 1; i < m; i++){ count[i] += count[i - 1]; } // 根据计数数组排序 for (int i = 0; i < n; i++){ array[--count[temparray[i]]] = temparray[i]; } }
// 添加主函数以检验BucketSort的正确性 intmain(){ int array[] = {5, 3, 8, 4, 2}; int n = sizeof(array) / sizeof(array[0]); int m = 10; // 假设数组中的最大值小于10 BucketSort(array, n, m); cout << "排序后的数组: "; for(int i = 0; i < n; i++) cout << array[i] << " "; cout << endl; return0; }
基数排序
这一页介绍了基数排序的基本概念和原理。
主要内容:
排序码由多个部分组成:
一个序列 (R = { r_0, r_1, \ldots, r_{n-1} } ) 中的每个排序码 ( K ) 由 ( d ) 位子排序码组成,可以表示为 ( K = (k_{d-1}, k_{d-2}, \ldots, k_1, k_0) )。
void RadixSorter<Record>::Sort(Record Array[], int n, int d, int r) { // n 为数组长度,d 为排序码数,r 为基数 Record *TempArray = new Record[n]; // 临时数组 int *count = newint[r]; // 计数器 int i, j, k; int Radix = 1;
for (i = 1; i <= d; i++) { // 取 Array[j] 的第 i 位排序码 for (j = 0; j < r; j++) // 分别对第 i 个排序码分配 count[j] = 0; // 初始化计数器均为 0
for (j = 0; j < n; j++) { // 统计每个桶中的记录数 // 取 Array[j] 的第 i 位排序码 k = (Array[j] / Radix) % r; count[k]++; // 相应计数器加 1 }
classNode { // 结点类 public: int key; // 结点的关键码值 int next; // 后继结点下标 };
classStaticQueue { // 静态队列类 public: int head; // 头指针 int tail; // 尾指针 };
// 基数排序算法 voidRadixSort(Record *Array, int n, int d, int r){ int i, first = 0; // first 指向静态链中的第一个记录 // 存放 r 个桶的静态队列 StaticQueue *queue = new StaticQueue[r]; // 建链,初始为 next 域指向下一个记录 for (i = 0; i < n - 1; i++) Array[i].next = i + 1; Array[n - 1].next = -1; // 链尾 next 为空
// 对第 i 个排序码进行分配和收集,共 d 趟 for (i = 0; i < d; i++) { Distribute(Array, first, i, r, queue); Collect(Array, first, r, queue); } delete[] queue; }
// 分配过程 voidDistribute(Record *Array, int first, int i, int r, StaticQueue *queue){ // first 为静态链中的第一个记录,i 为第 i 位排序码,r 为基数 for (int j = 0; j < r; j++) // 初始化 r 个队列 queue[j].head = -1; while (first != -1) { // 对整个静态链进行分配 int k = Array[first].key; // 取第 i 位排序码数字 for (int a = 0; a < i; a++) k = k / r; k = k % r; if (queue[k].head == -1) queue[k].head = first; else Array[queue[k].tail].next = first; queue[k].tail = first; // first 为子序列的尾部 first = Array[first].next; // 继续分配下一个记录 } }
// 收集过程 voidCollect(Record *Array, int &first, int r, StaticQueue *queue){ int last, k = 0; // 找到第一个非空队列 while (queue[k].head == -1) k++; first = queue[k].head; last = queue[k].tail; while (k < r - 1) { // 继续收集下一个非空队列 k++; if (queue[k].head != -1) { // 将非空序列连接起来 Array[last].next = queue[k].head; last = queue[k].tail; // 尾部记录 } } Array[last].next = -1; // 收集完毕 }