该篇博文长期更新,如有错误或者建议请评论留言,方便相互交流学习,谢谢。
1. 基本概念
1.1 稳定性
- 稳定算法:
排序序列中假设有几个比较关键词相等的元素,那么排序后这几个元素的前后相对位置不发生变化。 - 不稳定算法:
不能保证上述过程的算法称为不稳定算法。
算法的稳定性对于有些应用中比较重要。
1.2 时间性能
排序是数据处理中经常执行的一种操作,时间开销是衡量排序算法的一个重要标志。通常,在排序过程中需要进行下列两种操作:
- 比较两个关键字的大小
- 将元素从一个位置移动到另一位置
1.3 空间性能
空间性能是指排序过程中所需要的辅助存储空间的大小。辅助存储空间是除了存放待排序的数据所占用的存储空间之外,执行算法所需要的其他的存储空间。
2. 排序算法总结
2. 插入排序
插入排序的基本思想:
从初始的子集合开始,不断地把新的数据元素插入到有序子集合中的合适位置,使有序子集合中数据元素的个数不断增加,直到有序子集合的大小等于带排序的数据元素集合的大小为止。
扑克牌的抓牌过程就是一个典型的插入排序。
2.1 直接插入排序
顺序地把待排序的数据元素按其关键字值的大小插入到已排序子集合的适当位置,子集合的数据元素的个数逐渐增加,直至有序子集合的大小等于待排序数据元素集合的大小为止。
直接插入排序思想
- 把顺序表A的第一个元素A[0]作为已序集合,将A[1]元素插入到已序集合中,以此类推可以将整个序列排序完成。
void InsertSort(int a[], int n)
{
int i, j;
int tmp = a[0]; //已序序列
for(i=1; i<n; i++)
{
tmp = a[i]; //带插入元素
j = i-1; //待插入元素的前一个位置
while(j>-1 && tmp<a[j]) //当前元素查找合适插入位置
{
a[j+1] = a[j]; //向后移动已序序列
--j;
}
a[j + 1] = tmp; //插入待插入元素
}
}
2.2 希尔排序
/*
a[] 待排序序列 n待排序元素个数
d[] 增量序列 num增量序列长度
*/
void ShellSort(int a[], int n, int d[], int num)
{
int i, j, k, m, span;
int tmp;
for(m = 0; m < num; ++m)
{
span = d[m];
for(k = 0; k < span; ++k)
{
for(i = k + span; i < n; i += span)
{
tmp = a[i];
j = i - span;
while(j > -1 && tmp < a[j])
{
a[j + span] = a[j];
j -= span;
}
a[j + span] = tmp;
}
}
}
}
3. 选择排序
3.1 直接选择排序
void SelectSort(int a[], int n)
{
int i,j;
for(i=0; i<n; ++i)
{
for(j = i+1; j<n; ++j)
{
if(a[i] > a[j])
swap(&a[i], &a[j]);
}
}
}
3.2 堆排序
void AdjustHeap(int a[], int n, int k)
{
int i, j, flag;
int tmp;
i = k;
j = 2*i + 1;
tmp = a[i];
flag = 0;
while(j < n && flag != 1)
{
if(j < n-1 && a[j] < a[j+1])
++j;
if(tmp >= a[j])
{
flag = 1;
}
else
{
a[i] = a[j];
i = j;
j = 2*i + 1;
}
}
a[i] = tmp;
}
void CreatInitHeap(int a[], int n)
{
for(int i = (n-2)/2; i>=0; --i)
AdjustHeap(a,n,i);
}
void HeapSort(int a[], int n)
{
int i;
int tmp;
CreatInitHeap(a, n);
for(i = n-1; i > 0; --i)
{
tmp = a[0];
a[0] = a[i];
a[i] = tmp;
AdjustHeap(a, i, 0);
}
}
4. 交换排序
4.1 冒泡排序
void BubbleSort1(int a[], int n)
{
int i,j;
for(i = 0; i < n; ++i)
{
for(j = 1; j < n - i; ++j)
{
if(a[j-1] > a[j])
{
swap(&a[j-1], &a[j]);
}
}
}
}
void BubbleSort2(int a[], int n)
{
int i, j;
char flag = 0;
while(flag == 0)
{
flag = 1;
for(j = 1; j < n - i; ++j)
{
if(a[j-1] > a[j])
{
swap(&a[j-1], &a[j]);
flag = 0;
}
}
++i;
}
}
void BubbleSort3(int a[], int n)
{
int i, j;
int flag = n;
while(flag > 0)
{
i = flag;
flag = 0;
for(j = 1; j < i; ++j)
{
if(a[j-1] > a[j])
{
swap(&a[j-1], &a[j]);
flag = j;
}
}
}
}
4.2 快速排序
#include <iostream>
#include <stack>
using namespace std;
/*
对数组进行一次划分,arr[l]作为枢纽元素
l, r均为数据元素下标
*/
int partition(int *arr, int l, int r)
{
int i = l, j = r;
int key = arr[l]; //枢纽元素
while (i < j)
{
while (i < j && arr[j] >= key) j--; //从右往左找到一个比枢纽小的
if (i < j)
{
arr[i] = arr[j];
i++;
}
while (i < j && arr[i] < key) i++; //从右往左找到一个比枢纽大的
if (i < j)
{
arr[j] = arr[i];
j--;
}
}
arr[i] = key;
return i;
}
/*
对数组进行一次划分,arr[l]作为枢纽元素
l, r均为数据元素下标
*/
void QuickSort(int *arr, int l, int r)
{
if (l < r)
{
int par = partition(arr, l, r);
QuickSort(arr, l, par - 1);
QuickSort(arr, par + 1, r);
}
}
void QuickSort2(int *arr, int l, int r)
{
stack<int> tmp; //临时栈
if (l < r) //
{
int par = partition(arr, l, r); //
if (l < par - 1) //
{
tmp.push(l); //
tmp.push(par-1);
}
if (par + 1 < r)
{
tmp.push(par + 1);
tmp.push(r);
}
while (!tmp.empty())
{
r = tmp.top(); tmp.pop();
l = tmp.top(); tmp.pop();
par = partition(arr, l, r);
if (l < par - 1)
{
tmp.push(l); tmp.push(par - 1);
}
if (par + 1 < r)
{
tmp.push(par + 1); tmp.push(r);
}
}
}
}
int main()
{
int arr[] = { 3, 1, 2, 6, 7, 8, 9, 4, 5 };
int rt = partition(arr, 0, 8);
QuickSort2(arr, 0, 8);
cout << "rt = " << rt << endl;
for (int i = 0; i < 9; ++i)
cout << arr[i] << " ";
cout << endl;
return 0;
}
void QuickSort(int a[], const int low, const int high)
{
int i,j;
int tmp;
i = low;
j = high;
tmp = a[low];
while(i < j)
{
while(i<j && a[j]>=tmp) --j;
if(i < j)
{
a[i] = a[j];
++i;
}
while(i <j && a[i] < tmp) ++i;
if(i < j)
{
a[j] = a[i];
j--;
}
}
a[i] = tmp;
if(low < i-1)
QuickSort(a, low, i-1);
if(j + 1 < high)
QuickSort(a, j+1, high);
}