排序即将一组杂乱无章的数据按照一定规律顺次排列起来
分类:
按数据存储介质:内部排序和外部排序
按比较器个数:串行排序和并行排序
按主要操作:比较排序和基数排序
按辅助空间:原地排序和非原地排序
按稳定性:稳定排序和非稳定排序
按自然性:自然排序和非自然排序
插入排序:
直接插入排序:
代码实现:
void InsertSort(SqList& L)
{
int i, j;
for (i = 2; i <= L.length; i++)
{
if (L.r[i].key < L.r[i - 1].key)
{
L.r[0] = L.r[i];
for (j = i - 1; L.r[0].key < L.r[j].key; j--)
L.r[j + 1] = L.r[j];
L.r[j + 1] = L.r[0];
}
}
}
主函数:
int main()
{
int i,key;
SqList L;
ifstream in;
ofstream out;
in.open("input.txt");
out.open("output.txt");
cout << "请输入数据总数" << endl;
cin >> L.length;
for (i = 1; i <= L.length; i++)
in >> L.r[i].key;
InsertSort(L);
for (i = 1; i <= L.length; i++)
out<< L.r[i].key<<" ";
cout << "操作成功" << endl;
out.close();
return 0;
}
输出结果:
数据1
数据2
数据3
数据源
操作1
结果
操作2
结果
折半插入排序:
用折半查找法查找插入的位置
代码实现:
void BInsertSort(SqList& L)
{
int low, high, mid,i, j;
for (i = 2; i <= L.length; i++)
{
low = 1;
L.r[0] = L.r[i];
high = i - 1;
while (low <= high)
{
mid = (low + high) / 2;
if (L.r[0].key < L.r[mid].key) high = mid - 1;
else low = mid + 1;
}
for (j = i - 1; j >= high + 1; j--)
L.r[j + 1] = L.r[j];
L.r[high + 1] = L.r[0];
}
}
输出结果:
操作1
结果
操作2
结果
特点:
比顺序查找快;比较次数与初始排列无关;减少了比较次数,但没有减少移动次数;
希尔排序:
原理:
步骤:
代码实现:
void ShellInsert(SqList& L, int a/*间隔排序的间隔大小*/)
{
int j,k;
for (j = a + 1; j <= L.length; j++)
{
if (L.r[j].key < L.r[j - a].key)
{
L.r[0] = L.r[1];
for (k = j - a; k > 0 && (L.r[0].key < L.r[k].key); k = k - a)
L.r[k + a] = L.r[k];
L.r[k + a] = L.r[0];
}
}
}
void ShellSort(SqList&L, int s[], int t)
{
int i;
for (i = 0; i < t; i++)
ShellInsert(L, s[i]);
}
特点:
缩小增量;多遍插入排序;不宜在链式存储结构上使用
举例:
交换排序:
思想:
两两比较,若逆序则交换,直到全部排好为止
冒泡排序:
原理:
两两比较,按从小到大排序
代码实现:
void BubbleSort(SqList& L)
{
int i, j;
RedType x;
for (i = 1; i <= L.length - 1; i++)
{
for (j = 0; j <= L.length - 1; j++)
if (L.r[j].key > L.r[j + 1].key)
{
x = L.r[j];
L.r[j] = L.r[j + 1];
L.r[j + 1] = x;
}
}
}
改进:
添加一个标志
void BubbleSortPro(SqList& L)
{
int i, j,flag=1;
RedType x;
for (i = 1;(i <= L.length-1)&&flag==1; i++)
{
flag = 0;
for (j = 0; j <= L.length-1; j++)
if (L.r[j].key > L.r[j + 1].key)
{
flag = 1;
x = L.r[j];
L.r[j] = L.r[j + 1];
L.r[j + 1] = x;
}
}
}
输出结果:
数据1
结果
数据2
结果
快速排序:
原理:
通过一趟排序,将待排序的数据分割成两部分,其中一个部分的数据都比关键字小,一个部分都比关键字大,则可分别对这两部分数据再排序,直到全部有序
代码实现:
void QSort(SqList& L, int low, int high)
{
int foucus;
if (low < high)
{
foucus = FoucusFind(L, low, high);/*寻找中心点位置*/
QSort(L, low, foucus - 1);
QSort(L, foucus + 1,high);
}
}
int FoucusFind(SqList& L, int low, int high)
{
int foucuskey;
L.r[0] = L.r[low];
foucuskey = L.r[low].key;
while (low < high)
{
while (low < high && L.r[high].key >= foucuskey)
high--;
L.r[low] = L.r[high];
while (low < high && L.r[low].key <= foucuskey)
low++;
L.r[high] = L.r[low];
}
L.r[low] = L.r[0];
return low;
}
主函数:
QSort(L,1,L.length);
输出结果:
数据1
结果
数据2
结果
特点:不适用于对原本有序或基本有序的数据排序
选择排序:
简单排序:
原理:
选出最大或者最小的数据放在其最终位置
思路:
代码实现:
void SelectSort(SqList& L)
{
int i, j, k;
RedType t;
for (i = 1; i < L.length; i++)
{
j = i;
for (k = i + 1; k <= L.length; k++)
if (L.r[k].key < L.r[j].key)
j = k;
if (j != i)
{
t = L.r[i];
L.r[i] = L.r[j];
L.r[j] = t;
}
}
}
输出结果:
数据1
结果
数据2
结果
堆排序:
概念:
实质就是一个完全二叉树存储结构
实现:
代码实现(调整):
void HeapAdjust(int R[], int s, int t)
{
int i,a;
a = R[s];
for (i = 2 * s; i <= t; i = i*2)
{
if (i < t && R[i] < R[i + 1])
i++;
if (a >= R[i])break;
R[s] = R[i];
s = i;
}
R[s] = a;
}
调整:
优点:
仅需一个供交换用的辅助空间;在最坏情况下,时间复杂度也不大
缺点:
是不稳定的排序方法,不适用数据较少的情况
归并排序:
概念:
将两个或两个以上的有序子序列归并为一个有序序列
二路归并排序(建归并树):
基数排序:
基本思想:
分配加收集
举例:
排序比较总结:
总结:
排序的方法多种多样,应根据数据量的大小,和数据是否需要稳定(如*2,3,2;排序后为*2,2,3;则为稳定排序;如为2,*2,3;则为不稳定排序)来选择适合的排序方法