给一个n大小的数据进行排序,我们可以选择许多排序方法。各有优劣。
判断你一个算法的好坏。可以从他的比较次数和移动次数来划分。
排序需要的平均比较次数,最快比较速度和最慢比较速度,需要额外的空间已经稳定性。
比较速度取决于排好一次序需要比较几次。
稳定性是指当二个数是相同的时候,如果你不改变他的前后关系,则是稳定。改变了则不稳定。
下面是我搜集的一些算法。(从小到大排,处理很大的数据)
一:冒泡排序
平均比较次数:n*n
最少比较次数:n
最多比较次数:n*n
需要的额外空间:0
稳定性:稳定
方法,从头开始,二二比较,若右边小于左边则二者互换位,一轮下来最右边为最大数,第二轮得到第二大的数;设置标准位,如果一轮下来没有发生移位则排序结束;
int Bubble(int array[],int size) //传入数组首地址和大小,返回值是比较次数
{
int i,j,k,n=0;
for(i=0;i<size-1;i++) //i=0则得到最大的数,i=1得到第二大的数,最差的情况下需要的得到n-1大的数才能完成排序
{
k=0; //标志位
for(j=0;j<size-1-i;j++) //排序获得前n-i-1中最大的数
{
n++; //比较次数
if(array[j]>array[j+1])
{
int tem=array[j];
array[j]=array[j+1];
array[j+1]=tem;
k++;
}
}
if(0==k) //未发生移位代表排序完成
return n;
}
return n;
}
冒泡排序示意图:
二:鸡尾酒排序
平均比较次数:n*n
最少比较次数:n
最多比较次数:n*n
需要的额外空间:0
稳定性:稳定
方法:从头开始,俩俩比较找到最大数,当比较到末尾时,从末尾开始俩俩比较找到最小数,左右循环;当一次循环中没有发生位移则表示排序结束
void Exchange(int array[],int sub) //交换函数,传入一个数组和下标,领该下标下的成员与右成员交换数值
25 {
26 int tem=array[sub];
27 array[sub]=array[sub+1];
28 array[sub+1]=tem;
29 }
30 int Cocktail(int array[],int size) //传入一个数组和数组大小,令数组进行鸡尾酒排序
31 {
32 int i,j,k=0,n=0; //k是标志位,n是计算比较次数当作返回值
33 for(i=0;i<size/2;i++) //最多比较size-1次,一个循环比较二次,所以除以二
34 {
35 k=0;
36 for(j=n/2;j<size-1-n/2;j++) //右循环
37 if(array[j]>array[j+1])
38 {
39 k++;
40 Exchange(array,j);
41 }
42 n++;
43 if(0==k) //k==0代表排序完成
44 return size*n+n*(n-1)/2; //等差数列,返回的是比较次数
45 k=0;
46 for(j=j-1;j>=0+i;j--) //左循环
47 if(array[j]>array[j+1])
48 {
49 k++;
50 Exchange(array,j);
51 }
52 n++;
53 if(0==k)
54 return size*n+n*(n-1)/2;
55 }
56 return size*n+n*(n-1)/2;
57 }
鸡尾酒排序示意图
三 :选择排序
平均比较次数 n*n
最少比较次数 n*n
最多比较次数 n*n
需要额外的空间 0
稳定性 不稳定
方法:循环一次取一个最小值然后与第一个值进行交换,长度减一,继续循环,共循环n-1次即可排序完全;
int choice(int array[],int size)
59 {
60 int i,j,n=0,min,tem;
61 for(i=0;i<size-1;i++) //取n-1次最小数
62 {
63 min=i;
64 for(j=i;j<size;j++) //找到最小数
65 {
66 n++;
67 if(array[min]>array[j])
68 min=j;
69 }
70 tem=array[i];
71 array[i]=array[min];
72 array[min]=tem;
73 }
74 return n; //返回比较的次数
75 }
选择排序示意图
四 插入排序
平均比较次数 n*n
最少比较次数 n
最多比较次数 n*n
需要额外的空间 0
稳定性 稳定
方法 数组第一个已排好序,后一个数组成员若小于前一个则互换,直到该数组碰到小于它本身的数或者到头;
int insertion(int array[],int size)
77 {
78 int i,j,tem,n=0; //n计算比较次数,
79 for(i=1;i<size;i++) //默认第一个是已经排好序
80 {
81 j=i;
82 tem=array[j];
83 while(tem<array[j-1] && j!=0) //如果该数小于前一个数或还没到头则前移
84 {
85 array[j]=array[j-1];
86 j--;
87 n++;
88 }
89 n++;
90 array[j]=tem;
91 }
92 return n; /返回比较次数
93 }
示意图
五 二分插入
平均比较次数 n*n
最少比较次数 nlogn
最多比较次数 n*n
所需额外空间 0
稳定性 稳定
方法:从第二个数开始排序,之前的数已经排好序,用二分法查找中间的数与中间的数大小关系,知道找到该数应该排得位置并插入
94 int Binaryinsertion(int array[],int size)
95 {
96 int i,n=0,left,right,tem;
97 for(i=1;i<size;i++) //i之前的数已经排好序
98 {
99 right=i;
100 left=0;
101 while(left<right) //最终lef所在的位置为该数的位置
102 {
103 if(array[(right+left)/2]<=array[i])
104 left=(right+left)/2+1;
105 else
106 right=(right+left)/2-1;
107 n++;
108 }
109 tem=array[i];
110 right=i;
111 while(right!=left)//left所在位置总体往前挪一格
112 {
113 array[right]=array[right-1];
114 right--;
115 }
116 array[left]=tem;//插入
117 }
118 return n;//返回比较次数
119 }
示意图![](https://img-blog.csdn.net/20170804123034890?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2piMTIzc3c5OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
六 希尔排序
平均比较次数 nlogn~n*n
最少比较次数 n^1.3
最多比较次数 n*n
需要额外的空间 0
稳定性 不稳定
方法:每隔d个进行排序,当d等于3时,则数组第一个和第四个和(1+3d)n排序。排好之后d减少,直到d为1;d目前为止没有最佳;
int Hill(int array[],int size) //输入数组和数组大小
121 {
122 int i,j,tem,n=0,d; //d为步长,该函数步长依次为size/2,size/2/2,...1;
123 for(d=size/2;d>0;d/=2)
124 for(i=d;i<size;i++) //对同一步长的数进行插入排序
125 for(j=i,n++;array[j]<array[j-1] && j>=d;j-=d)
126 {
127 tem=array[j];
128 array[j]=array[j-1];
129 array[j-1]=tem;
130 n++;
131 }
132 return n;
133 }
134
示意图
七 归并排序
平均运算次数 nlogn
最多运算次数 nlogn
最少运算次数 nlogn
需要额外的空间 0
稳定性 稳定
方法:将一个size大小的数组先分为size/2个,每个组里有2个成员,将其排序。再分成四个一组进行排序,直到一组里的成员大于size个
134 int Merger(int array[],int size) //输入数组和数组大小
135 {
136 int i,j,right,left,n=0,tem;
137 for(i=2;i<size*2;i*=2) //先2个归并,依次乘二
138 for(j=0;j+1<size;j+=i) //j代表一个组
139 for(left=j,right=j+i/2;right<size && right<j+i && left!=j+i/2;) //j组里前i/2个和后i/2个已经排好序,将他俩合并;
140 {
141 if(array[right]<array[left])
142 {
143 tem=array[right];
144 array[right]=array[left];
145 array[left]=tem;
146 left++;
147 right++;
148 }
149 else
150 left++;
151 n++;
152 }
153 return n; //返回比较次数
154 }
155
示意图
八 堆排序
平均比较次数 nlogn
最多比较次数 nlogn
最少比较次数 nlogn
需要额外的空间 0
稳定性 不稳定
方法:将数组以二叉树进行排序,父节点大于二个子节点,每次排好序后,将根节点与最右边的叶节点交换,数组长度减一。
134 int n=0; //全局变量,计算比较次数
135 int two(int array[],int size,int ia) //输入数组,数组大小和已排好序的个数
136 {
137 int i=ia,j,tem,k=0,left;
138 for(j=1;j<size-i;j++) //j为父节点
139 {
140 for(left=j*2;left<j*2+2;left++) //j*2和j*2+1为j的二个子节点
141 {
142 n+=2; //比较了二次
143 if(left<=size-i && array[left-1]>array[j-1] ) //如果子节点大于父节点,二者交换
144 {
145 tem=array[left-1];
146 array[left-1]=array[j-1];
147 array[j-1]=tem;
148 k++;
149 }
150 }
151 }
152 return k;
153 }
154 int Heapsort(int array[],int size) //输入数组和数组大小
155 {
156 int i=0,tem,k=1;
157 while(k!=0) //使数组进行二叉树初始化
158 k=two(array,size,0);
159 for(i=0;i<size-1;i++) //将根提取出来
160 {
161 two(array,size,i);
162 tem=array[0];
163 array[0]=array[size-1-i];
164 array[size-1-i]=tem;
165 }
166 return n; //返回比较次数
167 }
示意图
九 快速排序
平均比较次数 nlogn
最少比较次数 nlogn
最多比较次数 n*n
需要的额外空间
稳定性 不稳定
方法:在数组里找个数当作标杆,然后与其他成员进行比较大于它的放右边,小于它的放左边。然后在它的左边和右边继续找个标杆,直到排好序
191 int n=0; //全局变量用来计算比较次数
192 int quick(int array[],int right,int left) //输入数组,数组的最左边的下标,数组的最右边下标
193 {
194 if(right<=left)
195 return n; //返回比较次数
196 int head=left,tail=left+1,now,tem; //以第一个数组成员做标杆与其他成员作比较,tail指向其他成员
197 while(tail<=right)//tail值为head+1到right
198 {
199 n++; //比较次数加一
200 if(array[tail]<array[head]) //如果成员比标杆小,则移到他左边
201 {
202 now=tail;
203 tem=array[tail];
204 while(now!=head)
205 {
206 array[now]=array[now-1];
207 now--;
208 }
209 array[head]=tem;
210 head++; //head下标加1
211 tail++; //tail下标加一
212 continue;
213 }
214 tail++;
215 }
216 quick(array,head-1,left); //将标杆左边的组进行排序
217 quick(array,right,head+1); //将标杆右边的组进行排序
218 }
示意图