比较各种排序算法的时间空间消耗
下面分别给出各算法的特性及伪代码
插入排序
特点:stable sort、In-place sort,最好O(N),最坏O(N^2)
冒泡排序
特点:stable sort、In-place sort
思想:通过两两交换,像水中的泡泡一样,小的先冒出来,大的后冒出来。
- 选择排序
特性:In-place sort,unstable sort。
思想:每次找一个最小值。最好情况时间:O(n^2),最坏情况时间:O(n^2)。
- 归并排序
特点:stable sort、Out-place sort
思想:运用分治法思想解决排序问题。最坏情况运行时间:O(nlgn),最佳运行时间:O(nlgn)
快速排序
改进当所有元素相同时的效率的Partition实现:
堆排序
- 计数排序
- 基数排序
代码实现:
#include<iostream>
#include<vector>
#include<algorithm>
#include<ctime>
#include<cstdlib>
using namespace std;
// 插入排序
void insert_sort(vector<int>& v, int l, int r){
if(l<r){
for(int i=l+1; i<=r; i++){
int j=i-1;
int key = v[i];
while(j>=l && v[j]>=key){
v[j+1] = v[j];
j--;
}
v[j+1] = key;
}
}
}
// 冒泡排序
void bubble_sort(vector<int>& v, int l, int r){
if(l<r){
bool flag = true; //表示是否有交换
for(int i=l; i<r; i++){
if(flag == false) return;
for(int j=r; j>i; j--){
if(v[j]<v[j-1]){
swap(v[j],v[j-1]);
flag = true;
}
}
}
}
}
// 选择排序
void select_sort(vector<int>& v, int l, int r){
if(l<r){
for(int i=l; i<r; i++){
int min = i;
for(int j=i+1; j<=r; j++){
if(v[j]<v[min]) min = j;
}
swap(v[min],v[i]);
}
}
}
// 归并排序
void merge(vector<int>& v, int l,int m, int r){
if(l<r && m<r){
int len1 = m-l+1;
int len2 = r-m;
int* a = new int[len1];
int* b = new int[len2];
for(int i=0; i<len1; i++) a[i] = v[l+i];
for(int i=0; i<len2; i++) b[i] = v[m+1+i];
int i,j;
int k=l;
i=0,j=0;
for( ;i<len1 && j<len2; ){
if(a[i]<b[j]){
v[k++] = a[i++];
}
else{
v[k++] = b[j++];
}
}
while(i<len1) v[k++] = a[i++];
while(j<len2) v[k++] = b[j++];
delete []a;
delete []b;
}
}
void merge_sort(vector<int>& v, int l, int r){
if(l<r){
int mid = (l+r)/2;
merge_sort(v,l,mid);
merge_sort(v,mid+1,r);
merge(v,l,mid,r);
}
}
// 快排
int partition(vector<int>& v, int l, int r){
int pivot = v[r];
int i=l-1;
for(int j=l; j<r; j++){
if(v[j]<pivot){
i++;
swap(v[i],v[j]);
}
}
i++;
swap(v[i],v[r]);
return i;
}
void quick_sort(vector<int>& v, int l, int r){
if(l<r){
int m = partition(v,l,r);
quick_sort(v,l,m-1);
quick_sort(v,m+1,r);
}
}
// 堆排序
int parent(int i){
return (i-1)/2;
}
int leftChild(int i){
return 2*i+1;
}
int rightChild(int i){
return 2*i+2;
}
void maxHeapify(vector<int>& v, int len, int i){
int lchild = leftChild(i);
int rchild = rightChild(i);
int maxPos;
if(lchild<len && v[lchild]>v[i]){
maxPos = lchild;
}
else{
maxPos = i;
}
if(rchild<len && v[rchild]>v[maxPos]){
maxPos = rchild;
}
if(maxPos != i){
swap(v[i],v[maxPos]);
maxHeapify(v,len, maxPos);
}
}
void buildHeap(vector<int>& v, int len){
for(int i=parent(len-1); i>=0; i--){
maxHeapify(v,len,i);
}
}
void heap_sort(vector<int>& v, int len){
buildHeap(v,len);
for(int i=len-1; i>0; i--){
swap(v[0],v[i]);
--len;
maxHeapify(v,len,0);
}
}
// 计数排序
void count_sort(vector<int>& v, int len, int k){
vector<int> a(len);
vector<int> b(k+1);
for(int i=0; i<=k; i++) b[i] = 0;
for(int i=0; i<len; i++) b[v[i]] += 1;
for(int i=1; i<=k; i++) b[i] = b[i-1]+b[i];
for(int i=len-1; i>=0; i--){
a[b[v[i]]-1] = v[i];
b[v[i]] -= 1;
}
for(int i=0; i<len; i++) v[i] = a[i];
}
// 基数排序
/*
* Get the spcific digit of given number.
* For example, number 234,
* the 0st digit is 4,
* the 1st digit is 3,
* the 2nd digit is 2,
* the 3th digit is 0.
*/
int GetNDigit(int nNumber, int nIdx)
{
for (int i = nIdx; i > 0; i--) {
nNumber /= 10;
}
return nNumber % 10;
}
/*
* Counting Sort the given array according to specific digit.
* array: 待排序数组.
* nLength: 待排序数组长度
* nIdxDigit: 排序要依据的位. 0为最低位,高位依次加1.
* nK: *nIdxDigit位上可能出现的最大数字(对10进制数排序则nK=9).
*/
void CountingSort_SpecificDigit(vector<int>& array, size_t nLength, int nIdxDigit, int nK=9)
{
if (0 == nLength || 0 == nK)
return;
int *digitNum = new int[nLength];
memset(digitNum, 0, sizeof(int)*nLength);
int *count = new int[nK+1];
memset(count, 0, sizeof(int)*(nK+1));
int *arrayResult = new int[nLength];
memset(arrayResult, 0, sizeof(int)*nLength);
// 数组digitNum[],保存每个元素指定位上的数字,作为排序依据
for (int idx = 0; idx<nLength; idx++)
digitNum[idx] = GetNDigit(array[idx], nIdxDigit);
// 先计数,count[idx]为值等于idx的元素的个数
for (int idx = 0; idx<nLength; idx++)
count[digitNum[idx]]++;
// 再累加,count[idx]为小于等于idx的元素的个数
for (int idx = 1; idx<nK+1; idx++)
count[idx] = count[idx] + count[idx-1];
// 从后向前循环(保证排序稳定), 根据指定位的数字大小
// 将array[idx]排在所有小于等于array[idx]的数(共count[digitNum[idx]]个)的后面
for (int idx=nLength-1; idx>=0; idx--)
{
arrayResult[count[digitNum[idx]]-1] = array[idx];
count[digitNum[idx]]--;
}
// 把排序结果写回原数组
for(int i=0; i<nLength; i++) array[i] = arrayResult[i];
delete [] digitNum;
delete [] count;
delete [] arrayResult;
}
/*
* 基数排序
* array: 待排序数组
* nLength: 待排序数组元素个数
* nDigit: 所有元素的最大位数
*/
void radix_sort(vector<int>& array, size_t nLen, int nDigit)
{
// 从最低位到最高位,依次调用计数排序
for (int idx=0; idx<=nDigit; idx++) {
CountingSort_SpecificDigit(array, nLen, idx);
}
}
void printVec(vector<int>& v){
int len = v.size();
for(int i=0; i<len; i++){
cout<<v[i]<<" ";
}
}
int main(){
srand(time(NULL));
vector<int> v(10);
for (int i = 0; i < 10; i++)
{
v[i] = rand()%100;
}
cout<<endl<<"排序前: ";
printVec(v);
insert_sort(v,0,v.size()-1);
cout<<endl<<"插入排序后: ";
printVec(v);
for (int i = 0; i < 10; i++)
{
v[i] = rand()%100;
}
cout<<endl<<"排序前: ";
printVec(v);
bubble_sort(v,0,v.size()-1);
cout<<endl<<"冒泡排序后: ";
printVec(v);
for (int i = 0; i < 10; i++)
{
v[i] = rand()%100;
}
cout<<endl<<"排序前: ";
printVec(v);
select_sort(v,0,v.size()-1);
cout<<endl<<"选择排序后: ";
printVec(v);
for (int i = 0; i < 10; i++)
{
v[i] = rand()%100;
}
cout<<endl<<"排序前: ";
printVec(v);
merge_sort(v,0,v.size()-1);
cout<<endl<<"归并排序后: ";
printVec(v);
for (int i = 0; i < 10; i++)
{
v[i] = rand()%100;
}
cout<<endl<<"排序前: ";
printVec(v);
quick_sort(v,0,v.size()-1);
cout<<endl<<"快速排序后: ";
printVec(v);
for (int i = 0; i < 10; i++)
{
v[i] = rand()%100;
}
cout<<endl<<"排序前: ";
printVec(v);
heap_sort(v,10);
cout<<endl<<"堆排序后: ";
printVec(v);
for (int i = 0; i < 10; i++)
{
v[i] = rand()%6;
}
cout<<endl<<"排序前: ";
printVec(v);
count_sort(v,10,5);
cout<<endl<<"计数排序后: ";
printVec(v);
v.resize(20);
for (int i = 0; i < 10; i++)
{
v[i] = rand()%100;
}
cout<<endl<<"排序前: ";
printVec(v);
radix_sort(v,20,1);
cout<<endl<<"基数排序后: ";
printVec(v);
system("pause");
return 0;
}