1:以个人使用频率及掌握程度进行如下排列。
2:以下都是从小到大排序。
3:一般记住哪个用哪个。建议:不要只会冒泡排序,数据量大了一定会超时。
4:小技巧: 可以C++的sort()函数,会方便很多。
5:最后: 如果有错误,请各位指出。
1、快速排序
1:时间复杂度O(nlog2n)
2:快速排序 - 百度百科
/*先调用划分函数,再进行左右递归排序*/
int partition(int a[],int i,int j)//注意:i、j都是下标。i为起始下标;j为末尾下标。
{
int t=a[i];
while(i<j){
while(a[j]>=t && i<j)j--;//右边的数都比t大;建议加上等号,这样效率更高
if(i<j)a[i++]=a[j];
while(a[i]<=t && i<j)i++;//左边的数都比t小;建议加上等号,这样效率更高
if(i<j)a[j--]=a[i];
}
a[i]=t;
return i;//返回下标
}
void QuickSort(int a[],int i,int j)
{
int k;
if(i<j){
k=partition(a,i,j);//使用划分函数把序列分成两部分
QuickSort(a,i,k-1);//对前半部分递归排序
QuickSort(a,k+1,j);//对后半部分递归排序
}
}
/*快速排序的填坑法*/
int Partition(int a[],int i,int j)
{
int start=i;//保留开头下标
int t=a[i];
while(i<j){
while(i<j && a[j]>t)j--;
while(i<j && a[i]<=t)i++;//注意:只能有一个等号,且必须是a[i]<=t的情况
if(i<j)//swap(a,i,j);//交换
{
int tem=a[i];
a[i]=a[j];
a[j]=tem;
}
//swap(a,start,i);//把基数填入
int tem=a[start];
a[start]=a[i];
a[i]=tem;
return i;
}
2、选择排序
1:O(n2)
2:选择排序_百度百科
void SelectionSort(int a[],int n)
{
int i,j;
int minId;//每一轮中最小值的下标
int t;
for(i=0;i<n-1;i++){//一共n-1趟
minId=i;
for(j=i+1;j<n;j++){//每次找出从a[j]到a[n-1]中最小的值和a[i]进行交换
if(a[j]<a[minId]){
minId=j;//记录当前一趟最小值的下标
}
}
/*交换*/
t=a[i];
a[i]=a[minId];
a[minId]=t;
}
}
3、冒泡排序
1:O(n2)
2:冒泡排序_百度百科
void BubbleSort(int a[],int n)
{
int i,j;
int t;
for(i=0;i<n-1;i++){//外层循环n-1趟
for(j=0;j<n-1-i;j++){//第一次比较n-1次 ;每趟比较到j<n-1-i
if(a[j]>a[j+1]){//相邻进行比较,逆序则进行交换
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
/*上面的for循环还可以写成这样,只不过改变了一下i的初始值*/
/*for(i=1;i<n;i++){//外层循环n-1趟
for(j=0;j<n-i;j++){//第一次比较n-1次 ;每趟比较到j<n-i
if(a[j]>a[j+1]){//相邻进行比较,逆序则进行交换
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}*/
}
4、插入排序
1:O(n2)
2:插入排序_百度百科
void InsertionSort(int a[],int n)
{
int i,j;
int t;
for(i=1;i<n;i++){
t=a[i];//t每次都等于当前要插入的数字
for(j=i-1;j>=0 && t<a[j];j=j-1){
a[j+1]=a[j];//往后挪:因为t小
}
a[j+1]=t;//将t插入到当前正确的位置:因为t刚好大于a[j],所以要插入到a[j+1]
}
}
5、希尔排序
1:O(n1.3~2)
2:希尔排序_百度百科
3:下面这两个函数唯一区别就是:是否把外层循环放在主函数。
4:把 ShellSort_2( ) 函数中的 g 换成 1 就是上面的插入排序。
void ShellSort_1(int a[],int n)
{
int i,j;
int t;
int g;//表示间隔gap
for(g=n/2;g>0;g=g/2){//初始g为数组长度的一半
for(i=g;i<n;i++){
t=a[i];
for(j=i-g;j>=0 && t<a[j];j=j-g){
a[j+g]=a[j];
}
a[j+g]=t;
}
}
}
#include<stdio.h>
void ShellSort_2(int a[],int n,int g)
{
int i,j;
int t;
/*把下面的g换成1就是上面的插入排序*/
for(i=g;i<n;i++){
t=a[i];
for(j=i-g;j>=0 && t<a[j];j=j-g){
a[j+g]=a[j];
}
a[j+g]=t;
}
}
int main()
{ int a[4]={1,4,5,7};
int g;//初始g等于数组长度的一半
for(g=4/2;g>0;g=g/2){//初始g=n/2;ShellSort_2()函数需要多次调用,上面的ShellSort_1()调用一次即可。
ShellSort_2(a,4,g);
}
//输出
for(i=0;i<n;i++){
printf("%d、 ",a[i]);
}
return 0;
}
6、归并排序
1:O(nlog2n)
2:归并排序_百度百科
/*针对数组a[],进行两段区间a[s1]-a[e1]和a[s2]-a[e2]的合并
a[]是要排序的数组;s1是起始下标;e1末尾下标;s2起始下标;e2末尾下标;b[]辅助数组*/
void Merge(int a[],int s1,int e1,int s2,int e2,int b[])
{
int k=s1;
int i=s1;//保留s1,便于后面数组复制
while(s1<=e1 && s2<=e2){
if(a[s1]<=a[s2]){
b[k++]=a[s1++];
}else{
b[k++]=a[s2++];
}
}
while(s1<=e1)b[k++]=a[s1++];
while(s2<=e2)b[k++]=a[s2++];
k--;
while(k>=i){//把排好的数据复制到数组a
a[k]=b[k];
k--;
}
}
void MergeSort(int a[],int i,int j,int b[])
{//a[]要排序的数组;i起始下标;j末尾下标;b[]辅助数组
int k;
if(i<j){
k=(i+j)/2;
MergeSort(a,i,k,b);
MergeSort(a,k+1,j,b);
Merge(a,i,k,k+1,j,b);//合并
}
}
7、堆排序
1:O(nlog2n)
2:堆排序_百度百科
#define LeftChild(i) (2*(i)+1)
void BuildDown(int a[],int n,int rootId)
{
int root;
int childId;
root=[rootId];
childId=LeftChild(rootId);
while(childId < n){
if(childId != n-1 && a[childId+1]>a[childId] )childId++;
if(root<a[childId]){
a[rootId]=a[childId];
rootId = childId;
childId = LeftChild(rootId);
}else{
break;
}
}
a[rootId]=root;
}
void HeapSort(int a[],int n)
{
int rootId;
int t;
int i;
for(int rootId=(n-2)/2; rootId>=0;rootId--){
BuildDown(a,n,rootId);
}
for(i=n-1;i>=0;i--){
t=a[0];
a[0]=a[i];
a[i]=t;
}
BuildDown(a,i,0);
}
8、基数排序
1:O(k(m+n))
2:基数排序_百度百科
9、桶排序
1:O(n+k)
2:桶排序_百度百科
10、计数排序
1:O(n)
2:计数排序_百度百科