排序算法的动画演示可以在以下网址获取:
乱入一个 二分查找
- http://www.atool.org/sort.php
- http://zh.visualgo.net/
类别 | 排序方法 | 时间复杂度 | 空间复杂度 | 稳定性 | ||
---|---|---|---|---|---|---|
平均情况 | 最好情况 | 最坏情况 | 辅助存储 | |||
插入排序 | 直接插入 | O(n2) | O(n) | O(n2) | O(1) | 稳定 |
shell 排序 | O(n1.3) | O(n) | O(n2) | O(1) | 不稳定 | |
选择排序 | 直接选择 | O(n2) | O(n2) | O(n2) | O(1) | 不稳定 |
堆排序 | O(n log2n) | O(n log2n) | O(n log2n) | O(1) | 稳定 | |
交换排序 | 冒泡排序 | O(n2) | O(n) | O(n2) | O(1) | 稳定 |
快速排序 | O(n log2n) | O(n log2n) | O(n2) | O(n log2n) | 不稳定 | |
归并排序 | O(n log2n) | O(n log2n) | O(n log2n) | O(1) | 稳定 | |
基数排序 | O(d(r+n)) | O(d(n+rd)) | O(d(r+n)) | O(rd+n) | 稳定 | |
注:基数排序的复杂度中,r 代表关键字的基数,d 代表长度,n 代表关键字的个数。 |
冒泡排序
- 比较相邻的元素。如果是降序(升序),就交换他们两个。
- 对每一对相邻元素作比较,从开始到结尾。则,最后的元素应该会是最大(最小)的数。
- 针对所有的元素重复以上的步骤(遍历),除了最后一个。

//代码用c++实现;
//传入参数:整型数组 list[]; 数组成员个数 n.
void BobbleSort(int list[], int n){
for(int i = 0; i < n-1; ++i){
for(int j = 0; j < n-i-1; ++j){
if(list[j] > list[j+1]){
std::swap(list[j],list[j+1]);
}
}
}
}
选择排序
- 从左至右遍历,找到最小(大)的元素,然后与第一个元素交换。
- 从剩余未排序元素中继续寻找最小(大)元素,然后与第二个元素进行交换。
- 以此类推,直到所有元素均排序完毕。
图片转自:http://blog.youkuaiyun.com/cike110120/article/details/46400229
//代码用c++实现;
//传入参数:整型数组 list[]; 数组成员个数 n.
void SelectSort(int list[], int n){
for(int i = 0; i < n-1; ++i){
int min = i;
for(int j = i+1; j < n; ++j){
if(list[min] > list[j]){
min = j;
}
}
std::swap(list[i],list[min]);
}
}
插入排序
- 从第一个元素开始,该元素可以认为已经被排序
- 取出下一个元素,在已经排序的元素序列中从后向前扫描
- 如果该元素(已排序)大于新元素,将该元素移到下一位置
- 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
- 将新元素插入到该位置中
- 重复步骤2
动画选自:http://www.jb51.net/article/30794.htm;
http://blog.youkuaiyun.com/tiredoy/article/details/39351845;
void InsertSort(int list[], int n){
int in, out;
for(out = 1; out < n; ++out){
int tmp = list[out];
in = out;
while(in > 0 && list[in-1] >= tmp){
list[in] = list[in-1];
--in;
}
list[in] = tmp;
}
}
快速排序
- 在数据集之中,选择一个元素作为”基准”(pivot)
- 所有小于”基准”的元素,都移到”基准”的左边;所有大于”基准”的元素,都移到”基准”的右边。
- 此时基准元素在其排好序后的正确位置
- 对”基准”左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。

// 参数列表中,left 表示最左侧的数据下标;right 表示最右侧数据下标;
void QuickSort(int list[], int left, int right){
if(left < right){
int i = left;
int j = right;
int pivot = list[left];//选取 pivot;
while(i < j){
while(i < j && list[j] >= pivot){ //从右向左找第一个小于x的数
j--;
}
if(i < j){
list[i++] = list[j];
}
while(i < j && list[i] < pivot){ //从左向右找第一个大于等于x的数
i++;
}
if(i < j){
list[j--] = list[i];
}
}
list[i] = pivot;//将 pivot 移至中间;
QuickSort(list, left, j-1);//对左侧数据递归快排;
QuickSort(list, j+1, right);//对右侧数据递归快排;
}
}
归并排序
> 常见的归并排序的空间复杂度为:O(n); > 空间复杂度为 O(1),需要特殊处理。可参考:http://blog.youkuaiyun.com/qiaofangjie/article/details/7559843- “分解”——将序列每次折半划分
- “合并”——将划分后的序列段两两合并后排序
- 递归,直至排序完成。


图片摘自:http://www.cnblogs.com/jingmoxukong/p/4308823.html
http://blog.youkuaiyun.com/tobeandnottobe/article/details/7192953#t1
void mergeSort(int *data, int l, int r){
int q;
if(l < r){ //只有一个或无记录时不须排序
q = (int)((l+r)/2); //将data数组分成两半
mergeSort(data, l, q); //递归拆分左数组
mergeSort(data, q+1, r); //递归拆分右数组
merge(data, l, q, r); //合并数组
}
}
void merge(int *data, int p, int q, int r)
{
int n1, n2, i, j, k;
int *left=NULL, *right=NULL;
n1 = q-p+1;
n2 = r-q;
left = (int *)malloc(sizeof(int)*(n1));
right = (int *)malloc(sizeof(int)*(n2));
for(i=0; i<n1; i++) //对左数组赋值
left[i] = data[p+i];
for(j=0; j<n2; j++) //对右数组赋值
right[j] = data[q+1+j];
i = j = 0;
k = p;
while(i<n1 && j<n2) //将数组元素值两两比较,并合并到data数组
{
if(left[i] <= right[j])
data[k++] = left[i++];
else
data[k++] = right[j++];
}
for(; i<n1; i++) //如果左数组有元素剩余,则将剩余元素合并到data数组
data[k++] = left[i];
for(; j<n2; j++) //如果右数组有元素剩余,则将剩余元素合并到data数组
data[k++] = right[j];
}
乱入一个 二分查找
int BinarySearch(int list[], int n, int x){
int low, high, mid;
low = 0;
high = n-1;
while( low <= high){
mid = (low + high)/2;
if( list[mid] == x){
return mid; //找到结果;
} else if( list[mid] < x){
low = mid +1;
} else if( list[mid] > x){
high = mid -1;
}
}
return -1;
}