C语言排序方法汇总
二级目录
在接下来的排序方法中,我们都采用4 1 2 6 5 3这个数列作为我们的栗子
一 冒泡排序
4 | 1 | 2 | 6 | 5 | 3 | |
---|---|---|---|---|---|---|
1 | 1 | 2 | 4 | 5 | 3 | 6 |
2 | 1 | 2 | 4 | 3 | 5 | 6 |
3 | 1 | 2 | 3 | 4 | 5 | 6 |
4 | 1 | 2 | 3 | 4 | 5 | 6 |
5 | 1 | 2 | 3 | 4 | 5 | 6 |
冒泡排序的本质就是每次将前n-i个数中的最大值换到第n-i+1位上去
代码如下
for (int i=1; i<=n; i++) {
for (int j=1; j<=n-i; j++) {
if(a[j+1]<a[j]) swap(&a[j+1],&a[j]);
}
优点:写起来简单
缺点:运算量过大每两个之间就要比较一次
二 快速排序
选择排序的重点在于设置一个基准值,将数列分为大于基准值和小于基准值的两个部分,再对两个部分重复操作,递归求解,这里将初始基准值设为2
4 | 1 | 2 | 6 | 5 | 3 | |
---|---|---|---|---|---|---|
1 | 2 | 1 | 4 | 6 | 5 | 3 |
2 | 1 | 2 | 4 | 3 | 5 | 6 |
3 | 1 | 2 | 3 | 4 | 5 | 6 |
第 一 次 : 1 − 6 第 二 次 : 1 − 2 3 − 6 第 三 次 : 3 − 4 5 − 6 第一次:1-6\\ 第二次 :1-2 \quad 3-6\\ 第三次: 3-4 \quad5-6 第一次:1−6第二次:1−23−6第三次:3−45−6
void quicksort(int left,int right)
{
int mid=a[(left+right)/2];
int i=left;
int j=right;
while(i<=j){
while(a[i]<mid) i++;
while(a[j]>mid) j--;
if(i<=j) {swap(&a[i],&a[j]);i++;j--;}
}
if(i<right) quicksort(i,right);
if(j>left) quicksort(left, j);
}
优点:运行速度较快
缺点:不稳定,在一些情况下可能会较慢(但肯定比冒泡快很多)
三 选择排序
即从n个数中取出最小的数,和第一位的数进行 交换,再对n-1个数重复操作
4 | 1 | 2 | 6 | 5 | 3 | |
---|---|---|---|---|---|---|
1 | 1 | 4 | 2 | 6 | 5 | 3 |
2 | 1 | 2 | 4 | 6 | 5 | 3 |
3 | 1 | 2 | 3 | 4 | 6 | 5 |
4 | 1 | 2 | 3 | 4 | 6 | 5 |
5 | 1 | 2 | 3 | 4 | 5 | 6 |
这种方法其实和冒泡的差别不大,只是减少了交换的次数,对冒泡进行了优化。
void choosesort()
{
for (int i=1; i<=n; i++) {
int minn=a[i], minx=i;
for (int j=i; j<=n; j++) {
if(a[j]<minn){minn=a[j];minx=j;}
}
swap(&a[i], &a[minx]);
}
}
四 插入排序
即将数列分为两个数列,一个为有序的,另一个为无序
初始 | 4 1 2 6 5 3 |
---|
不断将无序的数列插入到有序的数列中去
4 | 1 2 6 5 3 |
---|---|
1 4 | 2 6 5 3 |
以此类推
4 | 1 | 2 | 6 | 5 | 3 | |
---|---|---|---|---|---|---|
1 | 4 | 2 | 6 | 5 | 3 | |
1 | 2 | 4 | 6 | 5 | 3 | |
1 | 2 | 4 | 5 | 6 | 3 | |
1 | 2 | 3 | 4 | 5 | 6 |
void StraightSort(int len)
{
int tmp;
int i;
int j;
for (i = 1;i<=len;i++)
{
tmp = a[i];
for (j = i-1;j >= 1 && a[j] > tmp;j--)
{
a[j + 1] = a[j];
}
a[j + 1] = tmp;
}
}
优点:插入排序在数组量较小,数据较为整齐时速度较快
缺点:不稳定,若是出现较小的数字在靠后的位置,则会增加运算的复杂性(所以出现了希尔(shell)排序
五 希尔排序
为了更好的说明希尔排序,我们是用一组较为极端的数据
7 4 3 2 5 6 1 8
如果进行插入排序,如下
7 | 4 | 3 | 2 | 5 | 6 | 1 | 8 | |
---|---|---|---|---|---|---|---|---|
4 | 7 | 3 | 2 | 5 | 6 | 1 | 8 | |
3 | 4 | 7 | 2 | 5 | 6 | 1 | 8 | |
2 | 3 | 4 | 7 | 5 | 6 | 1 | 8 | |
2 | 3 | 4 | 5 | 7 | 6 | 1 | 8 | |
… | 手累了-_- |
我们要进行很多次的插入,比较,交换…所以不如先交换一些数据,使得数组更加整齐
7 | 4 | 3 | 2 | 5 | 6 | 1 | 8 | |
---|---|---|---|---|---|---|---|---|
1 | 4 | 3 | 2 | 5 | 6 | 7 | 8 |
有序性大大提高,便于插入排序
进入正文
在希尔排序中,我们从数组中按照一定的间距取出一个数组,对它进行排序,直至最终间距为1,即正常的插入排序
按照一定的间隔进行插入排序
void insert(int start,int gap,int len)
{
int i,j;
for (i=start; i<=len; i+=gap) {
int temp=a[i];
for (j=i-gap; j>=0&&a[j]>temp; j-=gap) {
a[j+gap]=a[j];
}
a[j+gap]=temp;
}
}
让初始值为 l e n 2 \frac {len} {2} 2len,再不断缩小
void shellsort(int len)
{
for (int i=len/2; i>=1; i/=2) {
for (int j=0; j<=i-1; j++) {
insert(j, i, len);
}
}
}
// 完整版的shell排序
void shellSort(int* a,int len)
{
for(int gap=len/2;gap>0;gap/=2)
{
//对于hk(即gap),hk+1,...,N-1中的每个位置i,把位置i上的元素放到i,i-hk,i-2hk......中的正确位置上
for(int i=gap;i<len;++i)
{
int tmp=a[i];
int j=i;
for(;j>=gap&&tmp<a[j-gap];j-=gap)
{
a[j]=a[j-gap];
}
a[j]=tmp;
}
}
优化了插入排序