常见算法:C语言中的排序算法--冒泡排序,选择排序,希尔排序
2012-04-11 17:43
453 查看
冒泡排序(Bubble Sort,台湾译为:泡沫排序或气泡排序)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端
维基百科:点击打开链接
另一种常见的写法
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到排序序列末尾(目前已被排序的序列)。以此类推,直到所有元素均排序完毕。
希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能。这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。
假设有一个很小的数据在一个已按升序排好序的数组的末端。如果用复杂度为O(n2)的排序(冒泡排序或插入排序),可能会进行n次的比较和交换才能将该数据移至正确位置。而希尔排序会用较大的步长移动数据,所以小数据只需进行少数比较和交换即可到正确位置。
一个更好理解的希尔排序实现:将数组列在一个表中并对列排序(用插入排序)。重复这过程,不过每次用更长的列来进行。最后整个表就只有一列了。将数组转换至表是为了更好地理解这算法,算法本身仅仅对原数组进行排序(通过增加索引的步长,例如是用
例如,假设有这样一组数[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ],如果我们以步长为5开始进行排序,我们可以通过将这列表放在有5列的表中来更好地描述算法,这样他们就应该看起来是这样:
然后我们对每列进行排序:
当我们以单行来读取数据时我们得到:[ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ].这时10已经移至正确位置了,然后再以3为步长进行排序:
排序之后变为:
最后以1步长进行排序(此时就是简单的插入排序了)。
维基百科:点击打开链接
/* 用选择法对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 ={{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"); }
相关文章推荐
- 常见算法:C语言中的排序算法--冒泡排序,选择排序,希尔排序
- C语言中的排序算法--冒泡排序,选择排序,希尔排序
- 算法分析中最常用的几种排序算法(插入排序、希尔排序、冒泡排序、选择排序、快速排序,归并排序)C 语言版
- 几种常见排序算法之Java实现(插入排序、希尔排序、冒泡排序、快速排序、选择排序、归并排序)
- C++各种常见排序算法 冒泡排序,插入排序,快排序,选择排序,希尔排序
- 算法_基本排序算法之冒泡排序,选择排序,插入排序和希尔排序
- 算法导论之插入排序,选择排序,归并排序,冒泡排序,希尔排序,堆排序,快速排序的c语言实现
- C语言8种排序算法及其实现 1.希尔排序 2.二分插入法 3.直接插入法 4.带哨兵的直接排序法 5.冒泡排序 6.选择排序 7.快速排序 8.堆排序
- 几种基本的排序算法(选择排序,冒泡排序,快速排序,归并排序,希尔排序)C语言实现
- 几种常见的排序算法,选择排序,冒泡排序,希尔排序,堆排序,快速排序,归并排序,基数排序的比较
- 笔试面试最常涉及到的12种排序算法(包括插入排序、二分插入排序、希尔排序、选择排序、冒泡排序、鸡尾酒排序、快速排序、堆排序、归并排序、桶排序、计数排序和基数排序)进行了详解。每一种算法都有基本介绍、算
- 各种排序算法实现——基数排序、归并排序、插入排序、冒泡排序、选择排序、快速排序、堆排序、希尔排序
- c语言中冒泡排序、插入排序、选择排序算法比较
- C#实现所有经典排序算法(选择排序,冒泡排序,快速排序,插入排序,希尔排序)
- 排序算法汇总(选择排序 ,直接插入排序,冒泡排序,希尔排序,快速排序...)
- 常见排序方法(冒泡排序、选择排序、插入排序、希尔排序和快速排序)
- 几种常用的排序算法的分析及java实现(希尔排序,堆排序,归并排序,快速排序,选择排序,插入排序,冒泡排序)
- 各种常见的排序,冒泡排序,选择排序,插入排序,希尔排序,堆排序,快速排序,基数排序,桶排序
- c语言中冒泡排序、插入排序、选择排序算法比较
- 常用算法--基本排序算法(冒泡排序,选择排序,插入排序,快速排序,归并排序,桶排序)