多种排序算法实现C语言

时间:2024.5.15

排序算法是面试笔试中必定要涉及的内容,常见的排序算法有:插入排序,冒泡排序,选择排序,快速排序,堆排序,希尔排序,归并排序,基数排序等,下面是我自己针对这几种算法进行一些总结和实现。

(1)按照时间性能来分,可以划分为三类排序算法:

1. O(nlogn): 快速排序,堆排序,归并排序,其中以快排为最佳;

2. O(n2): 直接插入排序,冒泡排序,简单选择排序,其中以直接插入排序为最佳,尤其对于那些关键字

近似有序的记录序列;

3. O(n): 只有基数排序,基数排序适合n值很大而关键字较小的序列。

(2)性能易变性:

当待排序列有序时,直接插入排序和冒泡排序能到达O(n),而对于快速排序而言,这反而是最不好的情况,此时时间性能蜕化为O(n2);简单选择排序,堆排序和归并排序的时间复杂度不随数列中关键字的分布而改变。

(3)稳定性:

选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,

冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。

各排序时间复杂度和空间复杂度对比表:

平台:VS 2008

算法实现:

---------------插入排序(直接插入)--------------

多种排序算法实现C语言

/*******************************************

*****描述:选定首元素为界,从第一个元素开始, *****和前面分界好的已经排好序的元素依次比较。 *******************************************/

#include "stdafx.h"

#include "stdio.h"

#define LEN 10

void sort_insert(int a[],int len)

{

int i,j,key;

for (i = 1; i < len; i++)

{

key = a[i];

//把i之前大于a[i]的数据向后移动

for (j = i - 1; ((a[j] > key) && j >= 0);j--)

{

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

}

a[j + 1] = key; //最后把最小的key赋值给首元素a[0] }

}

int _tmain(int argc, _TCHAR* argv[])

{

int a[LEN] = {3,6,2,1,0,10,9,12,5,10};

int k;

sort_insert(a,LEN);

for (k = 0; k < LEN; k++)

{

printf("%4d",a[k]);

}

return 0;

}

---------------冒泡排序--------------

#include "stdafx.h"

#include "stdio.h"

#define LEN 10

void bubble_sort(int arry[],int len)

{

int i,j,tmp;

for (i = 0; i < len - 1; i++)

{

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

{

if (arry[i] > arry[j])

{

tmp = arry[i];

arry[i] = arry[j];

arry[j] = tmp;

}

}

}

}

int _tmain(int argc, _TCHAR* argv[])

{

int a[LEN] = {3,6,2,1,0,10,9,12,5,10};

int k;

bubble_sort(a,LEN);

for (k = 0; k < LEN; k++)

{

printf("%4d",a[k]);

}

return 0;

}

---------------选择排序(简单选择排序)--------------

/*********************************************************** *****描述:

*****第一趟:从n个数中找出一个最小的,与第一个数互换; *****第二趟:从n-1个数中找出一个最小的,与第二个数互换; ***** .....

***** .....

*****第N趟:只剩下最后一个数,如果它为最大,则不互换。

***********************************************************/ #include "stdafx.h"

#include "stdio.h"

#define LEN 10

//交换数组中的两个数

void swap(int v[],int i,int j)

{

int tmp;

tmp = v[i];

v[i] = v[j];

v[j] = tmp;

}

//选择排序算法

void selection_sort(int arry[],int len)

{

int i,j,flag;

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

{

flag = j;

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

{

if (arry[i] < arry[flag])

{

flag = i;

}

}

swap(arry,j,flag);

}

}

int _tmain(int argc, _TCHAR* argv[])

{

int a[LEN] = {3,6,2,1,0,10,9,12,5,10};

int k;

selection_sort(a,LEN);

for (k = 0; k < LEN; k++)

{

printf("%4d",a[k]);

}

return 0;

}

---------------快速排序--------------

/******************************************* *****描述:把小于分区元素的数全部移动到它的左边 ********** 把大于分区元素的数全部移动到它的右边 ***********结果为:{小于X} X {大于X}

***********递归调用快排算法

*******************************************/ #include "stdafx.h"

#include "stdio.h"

#define LEN 10

//交换数组中的两个数

void swap(int v[],int i,int j)

{

int tmp;

tmp = v[i];

v[i] = v[j];

v[j] = tmp;

}

//快速排序算法

void quick_sort(int v[],int left,int right)

{

int i,last;

//最后一次递归结束出口

if (left >= right)

{

return;

}

//确定大概中间位置元素为分区元素

//把分区元素移动到最左边

swap(v,left,(left + right)/2);

last = left;

//分区:把小于分区元素的数全部移动到它的左边 //把大于分区元素的数全部移动到它的右边 //结果为:{小于X} X {大于X}

for (i = left + 1; i <= right; i++)

{

if (v[i] < v[left])

{

++last;

swap(v,last,i);

}

}

//恢复分区元素

swap(v,left,last);

//一次快排结束

//递归调用排序算法

quick_sort(v,left,last -1);

quick_sort(v,last + 1,right);

}

int _tmain(int argc, _TCHAR* argv[])

{

int a[LEN] = {3,6,2,1,0,10,9,12,5,10};

int k;

quick_sort(a,0,LEN - 1);

for (k = 0; k < LEN; k++)

{

printf("%4d",a[k]);

}

return 0;

}

算法具体执行过程:

举例:a[6] = {3,6,2,5,0,4,7};

选定中间元素(0+6)/2 = 3,即a[3]为5:

3 6 2 5 0 4 7

把5与left互换;

5 6 2 3 0 4 7

left和last都指向5;

i从left + 1开始,即从6开始;

如果小于a[left]内的数,则和++last互换,否则不执行操作; 执行过程如下:

5 6 2 3 0 4 7

5 2 6 3 0 4 7

5 2 3 6 0 4 7

5 2 3 0 6 4 7

5 2 3 0 4 6 7

5 2 3 0 4 6 7

最后交换left和last,此时last指向的是4

4 2 3 0 5 6 7

最终一次快排结果为:{4,2,3,0} 5 {6,7}

然后在{4,2,3,0}和{6,7}两个集合中递归快排

---------------堆排序--------------

#include "stdafx.h"

#include "stdio.h"

#define LEN 10

//调整筛选

void shift(int h[],int n,int m)

{

//h为数组,n为元素个数,m为从第m个元素开始调整 int j,tmp;

tmp = h[m];//保存每次需要调整的元素

j = 2 * (m + 1) - 1;

while (j <= n)

{

if ((j < n)&&(h[j] < h[j + 1]))

{

j += 1;

}

if (tmp < h[j])

{

h[m] = h[j];

m = j;//标记m

j = 2 * (m + 1) - 1;

}

else

{

j = n + 1;//跳出循环

}

}

h[m] = tmp;//把tmp保存的元素插入到正确位置 }

//堆排序

void HeapSort(int p[],int n)

{

int i,k,t;

k = n/2;

for (i = k -1; i >= 0; i--)

{

shift(p,n-1,i);

//i = k -1,n - 1都是与数组从0开始有关

}

for (i = n - 1; i >= 1; i--)

{

//把最大元素移到倒数第i个位置

//把倒数第i个元素移到堆顶

t = p[0];

p[0] = p[i];

p[i] = t;

shift(p,i-1,0);

}

}

int _tmain(int argc, _TCHAR* argv[]) {

int a[LEN] = {3,6,2,1,0,10,9,12,5,10}; int k;

HeapSort(a,LEN);

for (k = 0; k < LEN; k++)

{

printf("%4d",a[k]);

}

return 0;

}

---------------希尔排序--------------

/#include "stdafx.h"

#include "stdio.h"

#define LEN 10

void shellSort(int a[],int n)

{

int i,j,tmp,step;

for( step = n/2; step > 0; step = step/2 ) {

for(i = step;i < n;i++)

{

tmp = a[i];

j = i - step;

while((j >= 0) && (a[j]>tmp)) {

a[j + step] = a[j]; a[j] = tmp;

j = j - step;

}

}

}

}

int _tmain(int argc, _TCHAR* argv[]) {

int a[LEN] = {3,6,2,1,0,10,9,12,5,10}; int k;

shellSort(a,LEN);

for (k = 0; k < LEN; k++)

{

printf("%4d",a[k]);

}

return 0;

}

(end)


第二篇:C语言6种排序算法及其实现


C语言中常见的排序算法:冒泡排序法、选择排序法、插入排序法、快速排序法、希尔排序法、堆排序法6种。

1.冒泡排序

算法思想简单描述:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。

冒泡排序是稳定的。算法时间复杂度O(n2)。

main()

{

int a[10],i,j,k;

printf("This is a maopao sort\n");

printf("Please input 10 numbers for sort:");

for(i=0;i<10;i++)scanf("%d",&a[i]);

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

for(j=0;j<10-i;j++)if(a[j]>a[j+1])

{

k=a[j];

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

a[j+1]=k;

}

printf("The corret sort of those numbers is:");

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

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

printf("\n");

}

2.选择排序

算法思想简单描述:在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。

选择排序是不稳定的。算法复杂度O(n2)。

main()

{ int t,k,i,j,a[10];

printf("This is a select sort\n");

printf("Please input some number that you want to sort:");

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

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

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

{

k=i;

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

if(a[k]>a[j])

k=j;

t=a[i];

a[i]=a[k];

a[k]=t;

}

printf("The correct sort of those number is:");

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

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

printf("\n");

}

3.插入排序

算法思想简单描述:在要排序的一组数中,假设前面(n-1) [n>=2] 个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。

直接插入排序是稳定的。算法时间复杂度O(n2)。

main()

{ int a[10],j,i,m;

printf("this is a insert sort\n");

printf("Please input the 10 number you want to sort:");

for(i=0;i<10;i++)scanf("%d",&a[i]);

for(j=1;j<10;j++)

{ m=a[j];

for(i=j-1;i>=0;i--)

{

if(a[i]<m)

break;

else a[i+1]=a[i];

}

a[i+1]=m;

}

printf("The correct order of those numbers is:");

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

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

printf("\n");

}

算法思想简单描述:快速排序是对冒泡排序的一种本质改进。它的基本思想是通过一趟扫描后,使得排序序列的长度能大幅度地减少。在冒泡排序中,一次扫描只能确保最大数值的数移到正确位置,而待排序序列的长度可能只减少1。快速排序通过一趟扫描,就能确保以某个数为基准点的左边各数都比它小,右边各数都比它大。然后又用同样的方法处理它左右两边的数,直到基准点的左右只有一个元素为止。

显然快速排序可以用递归实现,当然也可以用栈化解递归实现。

快速排序是不稳定的。最理想情况算法时间复杂度O(nlog2n),最坏O(n2)。

quick(int first,int end,int L[])

{ int left=first,right=end,key;

key=L[first];

while(left<right)

{ while((left<right)&&(L[right]>=key))

right--;

if(left<right)

L[left++]=L[right];

while((left<right)&&(L[left]<=key))

left++;

if(left<right)L[right--]=L[left];}

L[left]=key;

return left;

}

quick_sort(int L[],int first,int end)

{ int split;

if(end>first)

{ split=quick(first,end,L);

quick_sort(L,first,split-1);

quick_sort(L,split+1,end);

}

}

main()

{ int a[10],i;

printf("This is a quick sort\n");

printf("Please input 10 numbers for sort:");

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

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

quick_sort(a,0,9);

printf("The correct sort of those numbers is:");

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

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

printf("\n");

}

算法思想简单描述:D.L.shell于19xx年在以他名字命名的排序算法中实现了这一思想。算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。

下面的函数是一个希尔排序算法的一个实现,初次取序列的一半为增量,以后每次减半,直到增量为1。

希尔排序是不稳定的。

void shell_sort(int *x, int n)

{

int h, j, k, t;

for (h=n/2; h>0; h=h/2) /*控制增量*/

{

for (j=h; j<n; j++) /*这个实际上就是上面的直接插入排序*/

{

t = *(x+j);

for (k=j-h; (k>=0 && t<*(x+k)); k-=h)

{

*(x+k+h) = *(x+k);

}

*(x+k+h) = t;

}

}

}

6.堆排序

算法思想简单描述:堆排序是一种树形选择排序,是对直接选择排序的有效改进。堆的定义如下:具有n个元素的序列(h1,h2,...,hn),当且仅当满足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1)(i=1,2,...,n/2)时称之为堆。在这里只讨论满足前者条件的堆。

由堆的定义可以看出,堆顶元素(即第一个元素)必为最大项。完全二叉树可以很直观地表示堆的结构。堆顶为根,其它为左子树、右子树。

初始时把要排序的数的序列看作是一棵顺序存储的二叉树,调整它们的存储顺序,使之成为一个堆,这时堆的根节点的数最大。然后将根节点与堆的最后一个节点交换。然后对前面(n-1)个数重新调整使之成为堆。依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。从算法描述来看,堆排序需要两个过程,一是建立堆,二是堆顶与堆的最后一个元素交换位置。所以堆排序有两个函数组成。一是建堆的渗透函数,二是反复调用渗透函数实现排序的函数。有最大堆和最少堆之分

堆排序是不稳定的。算法时间复杂度O(nlog2n)。

功能:渗透建堆

void sift(int *x, int n, int s)

{

int t, k, j;

t = *(x+s); /*暂存开始元素*/

k = s; /*开始元素下标*/

j = 2*k + 1; /*右子树元素下标*/

while (j<n)

{

if (j<n-1 && *(x+j) < *(x+j+1))/*判断是否满足堆的条件:满足就继续下一轮比较,否则调整。*/

{

j++;

}

if (t<*(x+j)) /*调整*/

{

*(x+k) = *(x+j);

k = j; /*调整后,开始元素也随之调整*/

j = 2*k + 1;

}

else /*没有需要调整了,已经是个堆了,退出循环。*/

{

break;

}

}

*(x+k) = t; /*开始元素放到它正确位置*/

}

功能:堆排序

void heap_sort(int *x, int n)

{

int i, k, t;

int *p;

for (i=n/2-1; i>=0; i--)

{

sift(x,n,i); /*初始建堆*/

}

for (k=n-1; k>=1; k--)

{

t = *(x+0); /*堆顶放到最后*/

*(x+0) = *(x+k);

*(x+k) = t;

sift(x,k,0); /*剩下的数再建堆*/

}

}

更多相关推荐:
c语言 排序算法总结

排序算法总结选择法排序:for(i=0;i9;i++){max=i;for(j=i+1;j10;j++)if(a[max]a[j])max=j;/*max为查找范围最大数所在元素下标*/if(max!=i)(i…

c语言排序算法总结(主要是代码实现)

冒泡排序(BubbleSort)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。…

C语言排序方法总结

C语言排序方法学的排序算法有插入排序合并排序冒泡排序选择排序希尔排序堆排序快速排序计数排序基数排序桶排序没有实现比较一下学习后的心得我不是很清楚他们的时间复杂度也真的不知道他们到底谁快谁慢因为书上的推导我确实只...

C语言排序算法小结

1稳定排序和非稳定排序简单地说就是所有相等的数经过某种排序方法后仍能保持它们在排序之前的相对次序我们就说这种排序方法是稳定的反之就是非稳定的比如一组数排序前是a1a2a3a4a5其中a2a4经过某种排序后为a1...

c语言排序算法总结

一希尔Shell排序法Shell排序法includeltstdiohgtvoidsortintvintnintgapijtempforgapn2gapgt0gap2设置排序的步长步长gap每次减半直到减到1fo...

排序算法总结C语言

排序算法总结一插入排序InsertionSort1基本思想每次将一个待排序的数据元素插入到前面已经排好序的数列中的适当位置使数列依然有序直到待排序数据元素全部插入完为止2排序过程示例初始关键字493865977...

C语言常用的三种排序方法总结与探讨

C语言常用的三种排序方法总结与探讨排序是程序设计中非常重要的内容它的功能是将一组无序的的数据排列成有序的数据序列经过排列后的数据要么是从大到小排列要么是从小到大排列一般也只有这两种情况例如我们统计班级学生的成绩...

【转载】排序算法介绍(C语言版)

转至程序员笔试知识点整理排序方法分类有插入选择交换归并计数等五种排序方法1插入排序中又可分为直接插入折半插入2路插入希尔排序这几种插入排序算法的最根本的不同点说到底就是根据什么规则寻找新元素的插入点直接插入是依...

abfcrpc算法大全常用c语言算法,包括数论算法,图论算法、排序算法、高精度

懒惰是很奇怪的东西它使你以为那是安逸是休息是福气但实际上它所给你的是无聊是倦怠是消沉它剥夺你对前途的希望割断你和别人之间的友情使你心胸日渐狭窄对人生也越来越怀疑一数论算法1求两数的最大公约数functiongc...

c语言中常用的排序算法

LinuxC排序算法总结以及运行效率比较includeltstdiohgtvoidsort1intaintnvoidsort2intaintnvoidsort3intaintnvoiddisplayintain...

C语言二路归并排序算法

原创文章来源C语言二路归并排序算法写了个二路归并的归并排序小代码直接贴上来filequickcppauthorincludeltiostreamgtusingnamespacestdvoidMergeintai...

C语言三种常用排序算法分析

C语言中三种常见排序算法分析何春燕一冒泡法起泡法算法要求用起泡法对10个整数按升序排序算法分析如果有n个数则要进行n1趟比较在第1趟比较中要进行n1次相邻元素的两两比较在第j趟比较中要进行nj次两两比较比较的顺...

c语言排序算法总结(36篇)