常用排序算法总结
2015-07-02 15:21
399 查看
注:所有排序都是写的由小到大排序的情况
1.插入排序
1)直接插入排序(稳定)
代码:
2)希尔排序 (不稳定)
希尔排序好的增量序列的共同特征:
http://baike.baidu.com/view/178698.htm?fromtitle=希尔排序算法&fromid=1801475&type=syn
① 最后一个增量必须为1
② 应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况
代码:
2.选择排序
1)直接选择排序(不稳定)
第一次从R[0]~R[n-1]中选取最小值,与R[0]交换,第二次从R[1]~R[n-1]中选取最小值,与R[1]交换,....,第i次从R[i-1]~R[n-1]中选取最小值,与R[i-1]交换,.....,第n-1次从R[n-2]~R[n-1]中选取最小值,与R[n-2]交换,总共通过n-1次,得到一个按排序码从小到大排列的有序序列·
初始状态
[ 8 3 2 1 7 4 6 5 ] 8 <--> 1
第一次 [ 1 3 2 8 7 4 6 5 ] 3 <--> 2
第二次 [ 1 2 3 8 7 4 6 5 ] 3 <--> 3
第三次 [ 1 2 3 8 7 4 6 5 ] 8 <--> 4
第四次 [ 1 2 3 4 7 8 6 5 ] 7 <--> 5
第五次 [ 1 2 3 4 5 8 6 7 ] 8 <--> 6
第六次 [ 1 2 3 4 5 6 8 7 ] 8 <--> 7
第七次 [ 1 2 3 4 5 6 7 8 ] 排序完成
代码:
2)堆排序(不稳定)---最大堆
最大堆性质:树中每个结点的值都大于或者等于任意一个子结点的值
代码:
给出了非递归和递归方法
3.交换排序
1)冒泡排序(稳定)
代码:
2)快速排序(不稳定)
代码:(使用尾递归的随机化快排)
4.归并排序(稳定)
代码:
5.线性时间排序
1)计数排序(稳定)
数组中每个数都在[0,k]之间
代码:
2)基数排序
代码:
(以十进制为例,设每一位的排序基于计数排序的思想)
3)桶排序
代码:
1.插入排序
1)直接插入排序(稳定)
代码:
void DirectInsertSort(int* arr, int len) { if(NULL==arr || len<=1) return; int keyIndex;//要插入的值下标 for(keyIndex=1;keyIndex<len;++keyIndex) { int key=arr[keyIndex]; //要插入的值 int sortedIndex=keyIndex-1; //前面已经排好序的值的下标,由后往前比较 while(sortedIndex>=0 && arr[sortedIndex]>key) { arr[sortedIndex+1]=arr[sortedIndex]; --sortedIndex; } arr[sortedIndex+1]=key; //注意这里的下标 sortedIndex+1 } }
2)希尔排序 (不稳定)
希尔排序好的增量序列的共同特征:
http://baike.baidu.com/view/178698.htm?fromtitle=希尔排序算法&fromid=1801475&type=syn
① 最后一个增量必须为1
② 应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况
代码:
void ShellSort(int* arr, int len) { if(NULL==arr || len<=1) return; for (int gap = len / 2; gap > 0; gap /= 2) //增量(gap/2.2时间效率更好) for (int keyIndex = gap; keyIndex < len; ++keyIndex) //插入排序即为gap=1的情况 { int key = arr[keyIndex]; int sortedIndex = keyIndex -gap; while(sortedIndex >= 0 && arr[sortedIndex] > key) { arr[sortedIndex+gap] = arr[sortedIndex]; sortedIndex -=gap; } arr[sortedIndex+gap] = key; } }
2.选择排序
1)直接选择排序(不稳定)
第一次从R[0]~R[n-1]中选取最小值,与R[0]交换,第二次从R[1]~R[n-1]中选取最小值,与R[1]交换,....,第i次从R[i-1]~R[n-1]中选取最小值,与R[i-1]交换,.....,第n-1次从R[n-2]~R[n-1]中选取最小值,与R[n-2]交换,总共通过n-1次,得到一个按排序码从小到大排列的有序序列·
初始状态
[ 8 3 2 1 7 4 6 5 ] 8 <--> 1
第一次 [ 1 3 2 8 7 4 6 5 ] 3 <--> 2
第二次 [ 1 2 3 8 7 4 6 5 ] 3 <--> 3
第三次 [ 1 2 3 8 7 4 6 5 ] 8 <--> 4
第四次 [ 1 2 3 4 7 8 6 5 ] 7 <--> 5
第五次 [ 1 2 3 4 5 8 6 7 ] 8 <--> 6
第六次 [ 1 2 3 4 5 6 8 7 ] 8 <--> 7
第七次 [ 1 2 3 4 5 6 7 8 ] 排序完成
代码:
void DirectChooseSort(int* arr, int len) { if(NULL==arr || len<=1) return; for(int keyIndex=0;keyIndex<len-1;++keyIndex) { int minIndex=keyIndex; for(int leftIndex=keyIndex+1;leftIndex<len;++leftIndex) //arr[keyIndex]~arr[len-1]最小值 { if(arr[minIndex]>arr[leftIndex]) minIndex=leftIndex; } if(minIndex!=keyIndex) { int temp=arr[minIndex]; arr[minIndex]=arr[keyIndex]; arr[keyIndex]=arr[minIndex]; } } }
2)堆排序(不稳定)---最大堆
最大堆性质:树中每个结点的值都大于或者等于任意一个子结点的值
代码:
给出了非递归和递归方法
//递归方法 void MaxHeapify_Recursively(int* arr, int idx, int len) { int leftIdx=2*idx+1; int rightIdx=2*idx+2; int maxIdx=idx;//idx,leftIdx和rightIdx中最小值的下标 if(leftIdx<len && arr[maxIdx]<arr[leftIdx]) maxIdx=leftIdx; if(rightIdx<len && arr[maxIdx]<arr[rightIdx]) maxIdx=rightIdx; if(maxIdx!=idx) { int temp=arr[idx]; arr[idx]=arr[maxIdx]; arr[maxIdx]=temp; MaxHeapify_Recursively(arr,maxIdx,len); } } //非递归循环方法 void MaxHeapify_Iteratively(int* arr, int idx, int len) { while(idx<len/2) { int leftIdx=2*idx+1; int rightIdx=2*idx+2; int maxIdx=idx;//idx,leftIdx和rightIdx中最小值的下标 if(leftIdx<len && arr[maxIdx]<arr[leftIdx]) maxIdx=leftIdx; if(rightIdx<len && arr[maxIdx]<arr[rightIdx]) maxIdx=rightIdx; if(maxIdx!=idx) { int temp=arr[idx]; arr[idx]=arr[maxIdx]; arr[maxIdx]=temp; idx=maxIdx; } else return; } } void BuildMaxHeap(int* arr, int len) { for(int i=len/2-1;i>=0;--i) MaxHeapify_Recursively(arr,i,len); } void MaxHeapSort(int*arr, int len) { if(NULL==arr || len<=1) return; BuildMaxHeap(arr,len); for(int i=len-1;i>=1;--i) { int temp=arr[0]; arr[0]=arr[i]; arr[i]=temp; MaxHeapify_Recursively(arr,0,i); } }
3.交换排序
1)冒泡排序(稳定)
代码:
void BubbleSort(int *arr, int len) { if(NULL==arr || len<=1) return; bool isOrdered=true; //判断在一次冒泡过程时没有发生交换,即为已经排序好 for(int i=1;i<len-1;++i) //冒泡找到第i大的数 for(int j=0;j<len-i;++j) { if(arr[j+1]<arr[j]) { int temp=arr[j]; arr[j]=arr[j+1]; arr[j+1]=temp; isOrdered=false; } if(isOrdered) break; } }
2)快速排序(不稳定)
代码:(使用尾递归的随机化快排)
void Swap(int & a, int &b) { int temp=b; b=a; a=temp; } int Partition(int *arr, int start, int end) { int index=rand()%(end-start+1)+ start; //产生[start,end]之间的随机整数 Swap(arr[index],arr[end]); int small=start-1; for(index=start;index<end;++index) { if(arr[index]<arr[end]) { ++small; if(small<index) Swap(arr[small],arr[index]); } } ++small; Swap(arr[small],arr[end]); return small; } void TailQuickSort(int *arr,int length, int start, int end) //尾递归 { if(NULL==arr || length<=1 || start<0 || end>=length) return; while(start<end) { int index=Partition(arr,start,end); if((index-start)<(end-index)) { TailQuickSort(arr,length, start,index-1); start=index+1; } if((index-start)>=(end-index)) { TailQuickSort(arr,length,index+1,end); end=index-1; } } }
4.归并排序(稳定)
代码:
void Merge(int* arr, int start, int end, int leftEnd) { int *pOrdered=new int[end-start+1]; int index=0; int leftBegin=start; int rightBegin=leftEnd+1; while(leftBegin<=leftEnd && rightBegin<=end) { if(arr[leftBegin]<=arr[rightBegin]) pOrdered[index++]=arr[leftBegin++]; else pOrdered[index++]=arr[rightBegin++]; } while(leftBegin<=leftEnd) pOrdered[index++]=arr[leftBegin++]; while(rightBegin<=end) pOrdered[index++]=arr[rightBegin++]; for(int i=0;i<index;++i) arr[start++]=pOrdered[i]; delete[] pOrdered; pOrdered=NULL; } void MergeSort(int*arr, int len, int start, int end) { if(NULL==arr || len<=1 || start<0 || end>=len) return; if(start<end) { int leftEnd=(end+start)/2; MergeSort(arr, len, start, leftEnd); MergeSort(arr,len, leftEnd+1, end); Merge(arr, start, end, leftEnd); } }
5.线性时间排序
1)计数排序(稳定)
数组中每个数都在[0,k]之间
代码:
void CountSort(int *arr ,int len, int k) { if(NULL==arr || len<=1 || k<0) return; int* countArr=new int[k+1]; int* sortedArr=new int[len]; for(int m=0;m<k+1;++m) countArr[m]=0; for(int i=0;i<len;++i) ++countArr[arr[i]]; for(int j=1;j<k+1;++j) countArr[j]+=countArr[j-1]; for(int l=len-1;l>=0;--l) { sortedArr[countArr[arr[l]]-1]=arr[l]; //注意这里的下标 countArr[arr[l]]-1 --countArr[arr[l]]; } for(int i=0;i<len;++i) arr[i]=sortedArr[i]; delete[] countArr; countArr=NULL; delete[] sortedArr; sortedArr=NULL; }
2)基数排序
代码:
(以十进制为例,设每一位的排序基于计数排序的思想)
int MaxBits(int* arr, int len,int base) //辅助函数,求数据的最大位数 { int nMaxBits = 1; for(int i = 0; i<len; ++i) { while(arr[i] >= base) { base *= 10; ++nMaxBits; } } return nMaxBits; } void RadixSort(int* arr, int len) //基数排序 { if(NULL==arr || len<=1) return; int base=10; int nMaxBits= MaxBits(arr,len,base); int* countArr=new int[base+1]; int* sortedArr=new int[len]; int radix=1; for(int i=0;i<nMaxBits;++i) //由低位到高位按照计数排序的思想排序 { for(int m=0;m<base+1;++m) countArr[m]=0; for(int i=0;i<len;++i) ++countArr[(arr[i]/radix)%base]; for(int j=1;j<base+1;++j) countArr[j]+=countArr[j-1]; for(int l=len-1;l>=0;--l) { int bitNum=(arr[l]/radix)%base; sortedArr[countArr[bitNum]-1]=arr[l]; //注意这里的下标 countArr[bitNum]-1 --countArr[bitNum]; } for(int i=0;i<len;++i) arr[i]=sortedArr[i]; radix*=10; } delete[] countArr; countArr=NULL; delete[] sortedArr; sortedArr=NULL; }
3)桶排序
代码:
相关文章推荐
- weka初步一
- 21. Merge Two Sorted Lists
- 【Leetcode Algorithm】Invert Binary Tree
- 攻克GRE阅读难关的方法
- 执行长达2分多钟的大型sql优化
- Service 服务基础学习
- lightOJ 1278 Sum of Consecutive Integers(数论,数学推导)
- angular js 使用$location问题整理
- HTTP协议详解(转载)
- Leetcode 112 Path Sum
- 关于交叉编译器默认体系结构的问题
- 【Leetcode Algorithm】Rectangle Area
- 学习网址
- 使用系统下载管理类DownloadManager
- 防SQL注入
- C#验证码
- 【转】Android下编译jni库的二种方法(含示例)
- 链式队列
- centos 7 密码忘记 如何进入修改
- 创建一个背景透明的UIViewController