各类排序算法总结

一、直接插入排序

先上代码

#include<stdio.h>
void insort(int s[],int n)
{
	int i,j;
	for(i=2;i<=n;i++)
	{
		s[0]=s[i];		//s[0]为要比较值的变量,要插入哪个值就把哪个值赋给s[0]以免数据丢失 
		j=i-1;			//i表示要插入的元素,则i-1为已排列好的数组的最右边元素的位置
		while(s[0]<s[j])
		{
			s[j+1]=s[j];	//若要插入值比最大值还小,则最大值右移一位(腾出位置)(从小到大排序)
			j--;		
			
		} 
		s[j+1]=s[0];	//在确定位置插入s[i] 
	}
} 
void main()
{
	int a[11],i;		//设置数组大小要加一,用于放a[0] 
	printf("请输入10个数据: \n");
	for(i=1;i<11;i++)
	{
		scanf("%d",&a[i]);
	}
	insort(a,10);
	printf("插入数据排序后的顺序:\n");
	for(i=1;i<11;i++)
	{
		printf("%5d",a[i]);
	}
	printf("\n");
}

方法:比如有一组数据
3 2 1 5 4
你想把它从小到大排序,直接插入的思想就是,你先取第一个数,也就是3,把3看做已经排列好的序列(一个数没有排大小之分所以不用管第一个数是多少),然后取第二个数也就是2,若2比3还小,那么3向右移,把2插入,以此类推完成排序。其中你要用到数组,这个数组的长度需要在原有序列的长度基础上加一,原因可见代码。

二、希尔排序

代码如下:

#include<stdio.h>
void shsort(int s[],int n)
{
	int i,j,d;
	d = n/2;				//确定固定增量值 
	while(d>=1)		 
	{
		for(i=d+1;i<=n;i++)	//数组下标从d+1开始进行直接插入排序 
		{
			s[0] = s[i];
			j = i-d;		//确定要进行比较的元素的最右边的位置 
			while((j>0)&&(s[0]<s[j]))
			{
				s[j+d]=s[j]; 
				j=j-d;
			}
			s[j+d]=s[0];	//在确定位置插入s[i] 
		}
		d=d/2;				//增量变为原来的一半 
	}
}
void main()
{
	int a[11],i;		//设置数组大小要加一,用于放a[0] 
	printf("请输入10个数据: \n");
	for(i=1;i<11;i++)
	{
		scanf("%d",&a[i]);
	}
	shsort(a,10);
	printf("排序后的顺序:\n");
	for(i=1;i<11;i++)
	{
		printf("%5d",a[i]);
	}
	printf("\n");
}

方法:希尔排序的方法相当于直接插入排序的升级版,它加入了固定增量d从而把数组分成了若干组,然后在若干组中用直接插入排好顺序,然后减小固定增量,使组的范围增大,看上去复杂了,因为最后仍有一遍对全体元素的直接插入排序,但是因为先前已经拍好了顺序,所以并不会更复杂。希尔排序适用于大型的数组。

三、冒泡排序

上代码:

#include<stdio.h>
void main()
{
	int i,j,t,a[10];
	printf("请输入10个数: \n");
	for(i=0;i<10;i++)
	{
		scanf("%d",&a[i]);
	}
	
	//排序部分
	for(i=0;i<10;i++)
	{
		for(j=0;j<10-i;j++)
		{
			if(a[j]>a[j+1])
			{
				t=a[j];
				a[j]=a[j+1];
				a[j+1]=t;
			}		
		}	
	}
	printf("排序后的顺序是: \n");
	for(i=0;i<10;i++)
	{
		printf("%5d",a[i]);
	} 
		
}

方法总结:冒泡排序是一种较稳定的算法,通过两个相邻元素的比较来排列顺序,这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。如果要对n个数进行冒泡排序,那么要进行n-1趟比较,在第j趟比较中要进行n-j次两两比较,趟数决定了两两比较的次数,这样就很容易将两个for循环联系起来了。

四、快速排序

这个可以参考连接,写的很清楚:
链接: 快速排序.

五、选择排序

代码如下:

#include<stdio.h>
void main()
{
	int i,j,t,a[10];
	printf("请输入10个数:\n");
	for(i=0;i<10;i++)
	{
		scanf("%d",&a[i]);
	}
	for(i=0;i<9;i++)
	{ 
		for(j=i+1;j<10;j++)
		{
			if(a[i]>a[j])
			{
				t=a[i];
				a[i]=a[j];
				a[j]=t;
			}
		}
	} 
	printf("排序后的顺序为:\n");
	for(i=0;i<10;i++)
	{
		printf("%3d",a[i]);
	}
 } 

方法总结:其实原理很简单,就是将第一个数与后面的数挨个两两比较,第一趟选出最小的数放数组的第一位,第二趟选出第二小的数放数组的第二位,以此类推排出顺序。代码很好理解也很好记。但是,在一趟选择,如果一个元素比当前元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中两个5的相对前后顺序就被破坏了,所以选择排序是一个不稳定的排序算法。

六、归并排序

#include<stdio.h>
void merge(int r[],int s[],int x1,int x2,int x3)
{
	int i,j,k;
	i = x1;					//第一部分开始位置 
	j = x2+1;				//第二部分开始位置 
	k = x1;
	while((i<=x2)&&(j<=x3))		//当i和j都在两个要合并的部分中时 
		if(r[i]<=r[j]) 				//筛选两部分中较小的元素放到数组s中 
		{
			s[k]=r[i];
			i++;
			k++;
		}
		else
		{
			s[k]=r[j];
			j++;
			k++;	
		}
		while(i<=x2)				//将x1~x2范围内为比较的数顺次加到数组r中 
			s[k++]=r[i++];
		while(j<=x3)				//将x2+1~x3范围内为比较的数顺次加到数组r中 
			s[k++]=r[j++];
		
 } 
void merge_sort(int r[],int s[],int m,int n)
{
	int p;
	int t[20];
	if(m==n)
		s[m]=r[m];
	else
	{
		p=(m+n)/2;
		merge_sort(r,t,m,p);
		//递归调用函数将r[m]~r[p]归并成有序的t[m]~t[p]
		merge_sort(r,t,p+1,n);
		//递归调用函数将r[m]~r[p]归并成有序的t[p+1]~t[n]
		merge(t,s,m,p,n);
		
	}
	  
}
void main()
{
	int a[11];
	int i; 
	printf("请输入10个数:\n");
	for(i=1;i<=10;i++)
	{
		scanf("%d",&a[i]);
		
	}
	merge_sort(a,a,1,10);
	printf("排序后的顺序是: \n");
	for(i=1;i<=10;i++)
	{
		printf("%5d",a[i]);	
	}
	printf("\n");  
	 
}

归并是将两个或多个有序记录序列合并成一个有序序列。归并方法有多种,一次对两个有序记录进行归并,称为二路归并排序,也有三路归并及多路归并排序。这次用的是二路归并排序,基本方法为:(1)将n个记录看成是n个长度为1
的有序字表。(2)将两两相邻的有序字表进行归并。(3)重复步骤(2),直到归并成一个长度为n的有序表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值