基本概念
排序算法的稳定性,若待排序表中有两个元素v1和v2,其对应的关键字key1=key2,且排序前v1在v2的前面,若使用某一排序算法之后,v1仍然在v2前面,则这个算法是稳定的,否则这个算法是不稳定的。
内部排序,排序期间元素全部存放在内存中的排序。
外部排序,排序期间元素无法全部同时存放在内存中,必须在排序的过程中根据要求不断地在内、外存之间移动的排序。
插入排序
直接插入排序
1)基本思想是每一次将一个待排序的记录按其关键字大小插入到前面已排好序的子序列中,直到全部记录插入完成。
2)待排序列A[0]作为哨兵,不存放元素。
3)时间复杂度O(n^2)。
4)稳定排序算法。
代码片
void InsertSort(ElemType T[], int n)
{
int i, j;
for( i=2;i<n;i++)//将T[2]-T[n]插入到前面已排序序列
if (T[i] < T[i - 1])//若T[i]小于前驱,则插入
{
T[0] = T[i];//T[0]为哨兵,不存元素
for (j = i - 1;T[0] < T[j];--j)//从后往前查找待插入位置
T[j + 1] = T[j];//向后挪
T[j + 1] = T[0];//复制到插入位置
}
}
折半插入排序
1)减少了比较元素的次数。
2)时间复杂度O(n^2).
3)稳定排序算法。
代码片
//折半插入排序
void BinInsertSort(ElemType T[], int n)
{
int i, j, high, low, mid;
for (i = 2;i < n;i++)//将T[2]-T[n]插入到前面已排序序列
{
T[0] = T[i];//T[i]暂存到T[0]中
low = 1, high = i - 1;
while (low <= high)//折半查找范围
{
mid = (low + high) / 2;
if (T[mid] > T[0])
high = mid - 1;//查左表
else
low = mid + 1;//查右表
}
for (j = i - 1;j >= high;--j)
T[j + 1] = T[j];//统一后移,留出插入位置
T[high + 1] = T[0];//插入位置赋值
}
}
希尔排序
1)基本思想:首先它把较大的数据集合分割成若干个小组(逻辑上分组),然后对每一个小组分别进行插入排序,当整个表中的数据已呈“基本有序”时,再对全体数据进行一次直接插入排序。
2)适用于数据量比较大的排序表。
3)时间复杂度与增量序列相关。
4)不稳定排序算法。
参考https://blog.csdn.net/qq_39207948/article/details/80006224
代码片
//希尔排序
void ShellSort(ElemType T[], int n)
{
int i, j, dk;//增量dk
for (dk = n / 2;dk >= 1;dk = dk / 2)//步长变化
for (i = dk + 1;i < n;i++)
if (T[i] < T[i - dk])
{
T[0] = T[i];
for (j = i - dk;j > 0 && T[0] < T[j];j -= dk)
T[j + dk] = T[j];//后移
T[j + dk] = T[0];//插入
}
}
完整代码
#include<iostream>__msvc_all_public_headers.hpp
using namespace std;
typedef int ElemType;
const int MAX = 100;
struct List
{
ElemType key[MAX];
int len;
};
//直接插入排序
void InsertSort(ElemType T[], int n)
{
int i, j;
for( i=2;i<n;i++)//将T[2]-T[n]插入到前面已排序序列
if (T[i] < T[i - 1])//若T[i]小于前驱,则插入
{
T[0] = T[i];//T[0]为哨兵,不存元素
for (j = i - 1;T[0] < T[j];--j)//从后往前查找待插入位置
T[j + 1] = T[j];//向后挪
T[j + 1] = T[0];//复制到插入位置
}
}
//折半插入排序
void BinInsertSort(ElemType T[], int n)
{
int i, j, high, low, mid;
for (i = 2;i < n;i++)//将T[2]-T[n]插入到前面已排序序列
{
T[0] = T[i];//T[i]暂存到T[0]中
low = 1, high = i - 1;
while (low <= high)//折半查找范围
{
mid = (low + high) / 2;
if (T[mid] > T[0])
high = mid - 1;//查左表
else
low = mid + 1;//查右表
}
for (j = i - 1;j >= high;--j)
T[j + 1] = T[j];//统一后移,留出插入位置
T[high + 1] = T[0];//插入位置赋值
}
}
//希尔排序
void ShellSort(ElemType T[], int n)
{
int i, j, dk;//增量dk
for (dk = n / 2;dk >= 1;dk = dk / 2)//步长变化
for (i = dk + 1;i < n;i++)
if (T[i] < T[i - dk])
{
T[0] = T[i];
for (j = i - dk;j > 0 && T[0] < T[j];j -= dk)
T[j + dk] = T[j];//后移
T[j + dk] = T[0];//插入
}
}
void print(List A)
{
for (int i = 1;i < A.len;i++)
cout << A.key[i] << endl;
}
void test()
{
List A = { {0,9,6,7,4,3,8,2,5,1},{10} };
print(A);
cout << "----------------" << endl;
//InsertSort(A.key, A.len);
//BinInsertSort(A.key, A.len);
ShellSort(A.key, A.len);
print(A);
}
int main()
{
test();
return 0;
}
交换排序
冒泡排序
1)时间复杂度O(n^2)
2)稳定排序算法
//冒泡排序
void BubbleSort(ElemType T[], int n)
{
bool flag;
for (int i = 0;i < n - 1;i++)//需要n-1趟排序
{
flag = false;//标记
for (int j=n-1;j>i;j--)//从后往前开始,从小往大排序
if (T[j]<T[j-1])
{
swap(T[j -1], T[j]);//交换
flag = true;
}
if (flag == false)
return;//退出
}
}
快速排序
1)空间复杂度O(log2n)。
2)时间复杂度O(nlog2n)。
3)不稳定排序算法。
//快速排序
int Partition(ElemType T[], int low, int high)
{
ElemType pivot = T[low];//将表中第一个元素设为枢值,进行划分
while (low < high)
{
while (low < high && T[high] >= pivot)//比枢值小的元素移动到左端
high--;
T[low] = T[high];
while (low < high && T[low] <= pivot)//比枢值大的元素移动到右端
low++;
T[high] = T[low];
}
T[low] = pivot;//枢值元素放到最终位置
return low;//返回最终位置
}
void QuickSort(ElemType T[], int low, int high)
{
if (low < high)
{
int pivotpos = Partition(T, low, high);//划分
QuickSort(T, low, pivotpos - 1);//递归
QuickSort(T, pivotpos + 1, high);
}
}
完整代码
#include<iostream>__msvc_all_public_headers.hpp
using namespace std;
typedef int ElemType;
const int MAX = 100;
struct List
{
ElemType key[MAX];
int len;
};
//冒泡排序
void BubbleSort(ElemType T[], int n)
{
bool flag;
for (int i = 0;i < n - 1;i++)//需要n-1趟排序
{
flag = false;//标记
for (int j=n-1;j>i;j--)//从后往前开始,从小往大排
if (T[j]<T[j-1])
{
swap(T[j -1], T[j]);//交换
flag = true;
}
if (flag == false)
return;//退出
}
}
//快速排序
int Partition(ElemType T[], int low, int high)
{
ElemType pivot = T[low];//将表中第一个元素设为枢值,进行划分
while (low < high)
{
while (low < high && T[high] >= pivot)//比枢值小的元素移动到左端
high--;
T[low] = T[high];
while (low < high && T[low] <= pivot)//比枢值大的元素移动到右端
low++;
T[high] = T[low];
}
T[low] = pivot;//枢值元素放到最终位置
return low;//返回最终位置
}
void QuickSort(ElemType T[], int low, int high)
{
if (low < high)
{
int pivotpos = Partition(T, low, high);//划分
QuickSort(T, low, pivotpos - 1);//递归
QuickSort(T, pivotpos + 1, high);
}
}
void print(List A)
{
for (int i = 0;i < A.len;i++)
cout << A.key[i] << endl;
}
void test()
{
List A = { {6,5,9,8,3,2,7},{7} };
print(A);
cout << "----------------" << endl;
//BubbleSort(A.key, A.len);
QuickSort(A.key, 0,A.len-1);
print(A);
}
int main()
{
test();
return 0;
}
选择排序
简单选择排序
1)基本思想:每一趟选取最小的元素,作为有序序列中的元素,直到第n-1趟做完。
2)时间复杂度O(n^2)。
3)稳定排序算法。
代码
//简单选择排序
void SelectSort(ElemType T[], int n)
{
int min = 0;
for (int i = 0;i < n-1 ;i++)//进行n-1次排序
{
min = i;
for (int j = i + 1;j < n;j++)//找到最小的元素下标
if (T[j] < T[min])
min = j;
if (min != i)
swap(T[i], T[min]);//交换
}
}
堆排序
1)时间复杂度O(nlog2n)。
2)不稳定排序算法。
代码
//建立大根堆
void AdjustDown(ElemType A[], int k, int len)//向下调整
{
int i = 0;
A[0] = A[k];
for (i = 2 * k;i <= len;i *= 2)
{
if (i < len && A[i] < A[i + 1])//选取较大的子节点
i++;
if (A[0] >= A[i])//满足条件,筛选结束
break;
else
{
A[k] = A[i];//将A值赋值到双亲节点上
k = i;//修改K值,向下筛选
}
}
A[k] = A[0];
}
void BuildMaxHeap(ElemType A[], int len)
{
for (int i = len / 2;i > 0;i--)//调整堆
AdjustDown(A, i, len);
}
//堆排序
void HeapSort(ElemType A[], int len)
{
BuildMaxHeap(A, len);
for (int i = len;i > 1;i--)
{
swap(A[i], A[1]);//输出堆顶元素
AdjustDown(A, 1, i - 1);//整理剩下的n-1个元素
}
}
完整代码
#include<iostream>__msvc_all_public_headers.hpp
using namespace std;
typedef int ElemType;
const int MAX = 100;
struct List
{
ElemType key[MAX];
int len;
};
//简单选择排序
void SelectSort(ElemType T[], int n)
{
int min = 0;
for (int i = 0;i < n-1 ;i++)//进行n-1次排序
{
min = i;
for (int j = i + 1;j < n;j++)//找到最小的元素下标
if (T[j] < T[min])
min = j;
if (min != i)
swap(T[i], T[min]);//交换
}
}
//建立大根堆
void AdjustDown(ElemType A[], int k, int len)//向下调整
{
int i = 0;
A[0] = A[k];
for (i = 2 * k;i <= len;i *= 2)
{
if (i < len && A[i] < A[i + 1])//选取较大的子节点
i++;
if (A[0] >= A[i])//满足条件,筛选结束
break;
else
{
A[k] = A[i];//将A值赋值到双亲节点上
k = i;//修改K值,向下筛选
}
}
A[k] = A[0];
}
void BuildMaxHeap(ElemType A[], int len)
{
for (int i = len / 2;i > 0;i--)//调整堆
AdjustDown(A, i, len);
}
//堆排序
void HeapSort(ElemType A[], int len)
{
BuildMaxHeap(A, len);
for (int i = len;i > 1;i--)
{
swap(A[i], A[1]);//输出堆顶元素
AdjustDown(A, 1, i - 1);//整理剩下的n-1个元素
}
}
void print(List A)
{
for (int i = 0;i < A.len;i++)
cout << A.key[i] << endl;
}
void test()
{
List A = { {0,6,5,9,8,3,2,7},{8} };
print(A);
cout << "----------------" << endl;
//SelectSort(A.key,A.len);
HeapSort(A.key, A.len-1);
print(A);
}
int main()
{
test();
return 0;
}
归并排序和基数排序
归并排序
1)空间复杂度O(n)。
2)时间复杂度O(nlog2n)。
3)稳定排序算法。
#include<iostream>__msvc_all_public_headers.hpp
using namespace std;
typedef int ElemType;
const int MAX = 100;
struct List
{
ElemType key[MAX];
int len;
};
int B[100];//辅助数组
void Merge(ElemType A[], int low, int mid, int high)//合并成一个有序表
{
int i, j, g;
for (int k = low;k <= high;k++)
B[k] = A[k];//将A中所有元素复制到B中
for (i = low, j = mid + 1, g = i;i <= mid && j <= high;g++)
{
if (B[i] <= B[j])//比较B的左右两端中的元素
A[g] = B[i++];//较小值赋值到A中
else
A[g] = B[j++];
}
while (i <= mid)//若第一个未检测完,复制
A[g++] = B[i++];
while (j <= high)//若第二个未检测完,复制
A[g++] = B[j++];
}
void MergeSort(ElemType A[], int low, int high)
{
if (low < high)
{
int mid = (low + high) / 2;//从中间划分两个子序列
MergeSort(A, low, mid);//左侧子序列进行递归排序
MergeSort(A, mid + 1, high);//右侧子序列进行递归排序
Merge(A, low, mid, high);//归并
}
}
void print(List A)
{
for (int i = 0;i < A.len;i++)
cout << A.key[i] << endl;
}
void test()
{
List A = { {0,6,5,9,8,3,2,7},{8} };
print(A);
cout << "----------------" << endl;
MergeSort(A.key, 0, A.len - 1);
print(A);
}
int main()
{
test();
return 0;
}
基数排序
1)空间复杂度O®,需借助r个队列。
2)时间复杂度O(d(n+r)),需要进行d趟分配和收集。
3)稳定排序算法。
参考:https://blog.csdn.net/u013761665/article/details/51695211
内部排序
外部排序
参考:https://blog.csdn.net/xushiyu1996818/article/details/84936832