常见算法:C语言中的排序算法--冒泡排序,选择排序,希尔排序

冒泡排序(Bubble Sort,台湾译为:泡沫排序或气泡排序)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端

/*

用选择法对10个数进行排序

*/

#include<stdio.h>

void main()

{

int i,j,a[10];

for(i=0;i<10;i++)

scanf("%d",&a[i]);

for(i=0;i<9;i++) 

{//n个数要进行n-1趟比较

for(j=0;j<=9-i;j++)          //每趟比较n-i次

if(a[j]>a[j+1])          //依次比较两个相邻的数,将小数放在前面,大数放在后面

{

int t=a[j];

a[j]=a[j+1];

a[j+1]=t;

}

}

for(i=0;i<10;++i)              //输出比较之后的数组

printf(" %d",a[i]);

}

另一种常见的写法

/*

冒泡排序的另外一种写法

*/

#include<stdio.h>

void BubbleSort(int a[],int n)

{

int i,j;

for(i=n-1;i>0;--i)          //从n-1循环的到0,也是n次

for(j=0;j<i;j++)

if(a[j]>a[j+1])

{

int temp=a[j];

a[j]=a[j+1];

a[j+1]=temp;

}

}

void main()

{

int a[10],i;

for(i=0;i<10;i++)

scanf("%d",&a[i]);

BubbleSort(a,10);

printf("排序后的数组:\n");

for(i=0;i<10;i++)

printf(" %d",a[i]);

}

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到排序序列末尾(目前已被排序的序列)。以此类推,直到所有元素均排序完毕。

#include<stdio.h>

void SelectSort(int a[],int n) 

    int i,j; 

    for(i=0;i<n-1;i++)              //n个数要进行n-1趟比较,每次确定一个最小数放在a[i]中 

    { 

        int k=i;                    //假设a[0]是最小的数,把下标0放在变量K里面, 

        for(j=i+1;j<n;j++)           

            if(a[k]>a[j])  k=j;    //如果a[k]>a[j] 前面的数比后面的数大,交换下标,此时k指向小的数 

        if(k!=i) 

        { 

            int temp=a[i]; 

            a[i]=a[k]; 

            a[k]=temp; 

        } 

    } 


void main() 

    int a[10],i; 

    for(i=0;i<10;i++) 

        scanf("%d",&a[i]); 

    SelectSort(a,10); 

    printf("排序后的数组:\n"); 

    for(i=0;i<10;i++) 

        printf(" %d",a[i]); 

希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能。这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。

假设有一个很小的数据在一个已按升序排好序的数组的末端。如果用复杂度为O(n2)的排序(冒泡排序或插入排序),可能会进行n次的比较和交换才能将该数据移至正确位置。而希尔排序会用较大的步长移动数据,所以小数据只需进行少数比较和交换即可到正确位置。

一个更好理解的希尔排序实现:将数组列在一个表中并对列排序(用插入排序)。重复这过程,不过每次用更长的列来进行。最后整个表就只有一列了。将数组转换至表是为了更好地理解这算法,算法本身仅仅对原数组进行排序(通过增加索引的步长,例如是用i += step_size而不是i++)。

例如,假设有这样一组数[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ],如果我们以步长为5开始进行排序,我们可以通过将这列表放在有5列的表中来更好地描述算法,这样他们就应该看起来是这样:

13 14 94 33 82

25 59 94 65 23

45 27 73 25 39

10

然后我们对每列进行排序:

10 14 73 25 23

13 27 94 33 39

25 59 94 65 82

45

当我们以单行来读取数据时我们得到:[ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ].这时10已经移至正确位置了,然后再以3为步长进行排序:

10 14 73

25 23 13

27 94 33

39 25 59

94 65 82

45

排序之后变为:

10 14 13

25 23 33

27 25 59

39 65 73

45 94 82

94

最后以1步长进行排序(此时就是简单的插入排序了)。

//希尔排序

#include<stdio.h>

#define LT(a,b) ((a)<(b))

#define MAX_SIZE 20

#define T 3   

#define N 10

typedef int KeyType;

typedef int InfoType;

typedef struct

{

KeyType key;

InfoType otherinfo;

}RedType;

typedef struct

{

RedType r[MAX_SIZE+1];

int length;

}SqList;

void PrintSqList(SqList L)

{

int i;

for(i=1;i<L.length;i++)

{

printf("(%d %d)",L.r[i].key,L.r[i].otherinfo);

}

printf("\n");

}

int  PrintSqlListKey(SqList L)

{

int i;

for(i=1;i<L.length;i++)

{

printf("%d ",L.r[i].key);

}

printf("\n");

return 0;

}

void ShellInsert(SqList &L,int dk)

{

int i,j;

for(i=dk+1;i<=L.length;i++)

{

if LT(L.r[i].key,L.r[i-dk].key)

{

L.r[0]=L.r[i];

for(j=i-dk;j<0&& LT(L.r[i].key,L.r[j].key);j-=dk)

{

L.r[j+dk]=L.r[j];

}

L.r[j+dk]=L.r[0];

}

}

}

void ShellSort(SqList &L,int dlta[],int t)

{

int k;

for(k=0;k<t;k++)                                  //对所有增量序列

{

ShellInsert(L,dlta[k]);

printf("dlta[%d]=%d,第%d趟排序结果(仅输出关键字):",k,dlta[k],k+1);

PrintSqlListKey(L);

}

}

void main()

{

RedType d[N]={{49,1},{38,2},{65,3},{97,4},{76,65},{13,6},{27,7},{49,8},{55,9},{4,10}};

SqList m;

int i,dt[T]={5,3,1};

for(i=0;i<N;i++)

{

m.r[i+1]=d[i];

}

m.length=N;

printf("希尔排序前:\n");

PrintSqList(m);

printf("\n");

ShellSort(m,dt,T);

printf("希尔排序后:\n");

PrintSqList(m);

printf("\n");

}

欢迎工作一到五年的Java工程师朋友们加入Java学习之路:733234221

群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • 我和你,有过委屈,没有什么不同。身不由己,人生出不了大事故,撑死了不过是一段段睡前小故事而已。
    六号梦阅读 149评论 5 1
  • 一直以来以为做自己喜欢的事便会快乐!便会开心,今天一席话,顿然开悟!做自己喜欢的事就会没有烦恼吗?答案当然是否定的...
    夫子书社阅读 223评论 0 0
  • JVM垃圾回收机制 提到Java垃圾回收机制就不得不提到一个方法: system.gc()用于调用垃圾收集器,在调...
    天青色的鱼儿阅读 192评论 0 0