前言
把排序算法忘光了,回顾《数据结构》严蔚敏版,并看了网上的几篇文章后,随再做一次总结。本文不会具体介绍每一个算法,我觉得要具体看,可以看《数据结构》这本书,写得很好,不懂的再百度补充知识,主要是每一种方式的实现展示出来。
他们的性能比较:
排序算法C++实现
1.插入排序
1.1.直接插入排序
/*
* 直接插入排序
* int a[]为需要排序的数组
* start为起始位置,要求start>=1,因为a[0]要作为“哨兵”使用
* end为结束位置
*/
void InsertSort(int a[], int start, int end)
{
int i, j;
for(i = start + 1; i <= end; i++) {
if(a[i] < a[i-1]) {
a[0] = a[i];
a[i] = a[i-1];
for(j = i - 2; a[0] < a[j]; --j) {
a[j+1] = a[j];
}
a[j+1] = a[0];
}
}
}
1.2.希尔排序
/*
* 希尔排序
* int a[]为需要排序的数组
* start为起始位置,要求start>=1,因为a[0]是暂存单元,不是哨兵
* end为结束位置
*/
void ShellInsert(int a[], int start, int end, int dk)
{
int i, j;
for(i = dk + 1; i <= end; ++i) {
if(a[i] < a[i-dk]) {
a[0] = a[i];
for(j = i - dk; j > 0 && a[0] < a[j]; j-=dk) {
a[j+dk] = a[j];
}
a[j+dk] = a[0];
}
}
}
void ShellSort(int a[], int start, int end)
{
int dt[3] = {5, 3, 1}, t = 3;
for(int k = 0; k < t; ++k) {
ShellInsert(a, start, end, k);
}
}
2.交换排序
2.1.冒泡排序
/*
* 冒泡排序
* int a[]为需要排序的数组
* start为起始位置,要求start>=1
* end为结束位置
*/
void BubbleSort(int a[], int start, int end)
{
int m = end - 1;
bool flag = true;
for (int i = start; i <= end - 1 && flag; ++i) {
flag = false;
for(int j = 1; j <= end - i; ++j) {
if(a[j] > a[j+1]) {
flag = true;
int t = a[j]; a[j] = a[j+1]; a[j+1] = t;
}
}
}
}
2.2.快速排序
/*
* 快速排序
* int a[]为需要排序的数组
* start为起始位置,要求start>=1,因为a[0]是暂存单元,不是哨兵
* end为结束位置
*/
int Partition(int a[], int low, int high)
{
int pivotkey = a[low];
while (low < high) {
while (low < high && a[high] >= pivotkey) --high;
a[low] = a[high];
while (low<high && a[low] <= pivotkey) ++low;
a[high] = a[low];
}
a[low] = pivotkey;
return low;
}
void QSort(int a[], int low, int high)
{
if(low < high) {
int pivotloc = Partition(a, low, high);
QSort(a, low, pivotloc - 1);
QSort(a, pivotloc + 1, high);
}
}
3.选择排序
3.1.简单选择排序
/*
* 简单选择排序排序
* int a[]为需要排序的数组
* start为起始位置,要求start>=1
* end为结束位置
*/
void SelectSort(int a[], int start, int end)
{
for (int i = start; i <= end; i++) {
int k = i;
for (int j = i + 1; j <= end; j++) {
if (a[k] > a[j]) { k = j; }
}
if (k!=i) {
int t = a[i]; a[i] = a[k]; a[k] = t;
}
}
}
3.1.堆排序
/*
- 堆排序
- int a[]为需要排序的数组
- start为起始位置,要求start>=1
- end为结束位置
- 最坏O(nlog2n),而快排最坏O(n^2),当记录较多时较为高效
*/
void BuildMaxHeap(int heap[], int len) {
for (int i = len/2-1; i >= 0; i--) {
if ((2*i+1) < len && heap[i] < heap[2*i+1]) {
// 根结点大于左子树
int temp = heap[i];
heap[i] = heap[2*i+1];
heap[2*i+1] = temp;
if (2*(2*i+1)+1 < len && heap[2*i+1] < heap[2*(2*i+1)+1]
|| 2*(2*i+1)+2 < len && heap[2*i+1] < heap[2*(2*i+1)+2]) {
//检查交换后的左子树是否满足大顶堆性质,如不满足,则重新调整子树结构
BuildMaxHeap(heap, len);
}
}
if ((2*i+2) < len && heap[i] < heap[2*i+2]) {
int temp = heap[i];
heap[i] = heap[2*i+2];
heap[2*i+2] = temp;
if (2*(2*i+2)+1 < len && heap[2*i+2] < heap[2*(2*i+2)+1]
|| 2*(2*i+2)+2 < len && heap[2*i+1] < heap[2*(2*i+2)+2]) {
BuildMaxHeap(heap, len);
}
}
}
}
void HeapSort(int a[], int len) {
for (int i = len; i > 0; i--) {
BuildMaxHeap(a, i);
//交换根结点和数组末尾元素的值
int temp = a[0];
a[0] = a[i-1];
a[i-1] = temp;
}
}
4.归并排序
/*
* 归并排序
* int array[]为需要排序的数组
* low为起始位置,要求start>=1
* high为结束位置
* cnt为求逆序对数目,是归并排序的拓展
*/
// 合并数组,排好序,然后在拷贝到原来的数组array
int cnt = 0;
void Merge(int array[], int low,int mid, int high, int temp[]) {
int i = low;
int j = mid + 1;
int k = 0;
while (i <= mid && j <= high ) {
if (array[i] <= array[j]) temp[k++] = array[i++];
else {
temp[k++] = array[j++];
cnt += mid - i + 1;//求逆序对数目
}
}
while (i <= mid) temp[k++] = array[i++];
while (j <= high) temp[k++] = array[j++];
for (int p = 0; p < k; p++) array[low + p] = temp[p];
}
// 归并排序,将数组前半部分后半部分分成最小单元,然后在合并
void MSort(int array[], int low, int high, int temp[]) {
if (low == high) temp[low] = array[low];
else {
int mid = (low + high) / 2;
MSort(array, low, mid, temp);
MSort(array, mid + 1, high, temp);
Merge(array, low, mid, high, temp);
}
}
// 在这里创建临时数组,节省内存开销,因为以后的temp都是在递归里使用的。
void MergeSort(int array[], int low, int high) {
int *temp = new int[high+1];
MSort(array, low, high, temp);
}
5.基数排序
参考
《数据结构》严蔚敏版
轻松学习排序算法
面试准备之六大排序算法篇
数据结构常见的八大排序算法(详细整理)
八大排序算法总结与java实现