算法基础:基本排序算法原理、实现与总结

所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。

一 选择排序

选择排序很简单,他的步骤如下:

  1. 从左至右遍历,找到最小(大)的元素,然后与第一个元素交换。
  2. 从剩余未排序元素中继续寻找最小(大)元素,然后与第二个元素进行交换。
  3. 以此类推,直到所有元素均排序完毕。

实现:

#include<stdio.h>
#include<stdlib.h>
typedef int Item;
#define key(A) (A)
#define less(A,B) (key(A)<key(B))
#define exch(A,B) {Item t=A;A=B;B=t;}
#define compexch(A,B) if(less(B,A)) exch(A,B)
void selectSort(Item a[],int l,int r)
{
	int i,j;
	for(i=l;i<=r;i++)
	{
		int min=i;
		for(j=i;j<=r;j++)
		{
			if(less(a[j],a[min]))
				min=j;
		}	
		exch(a[min],a[i]);
	}
}

int main(int argc,char *argv[])
{
	int N=atoi(argv[1]);
	Item *a=(Item*)malloc(N*sizeof(Item));
	for(int i=0;i<N;i++)
		a[i]=1000*(1.0*rand()/RAND_MAX);
	for(int i=0;i<N;i++)
		printf("%3d ",a[i]);
	printf("\n");
	selectSort(a,0,N-1);
	for(int i=0;i<N;i++)
		printf("%3d ",a[i]);
	printf("\n");
	return 0;
}

二 冒泡排序

冒泡排序算法实际上也是一种选择排序算法,实现原理也比较简单。

  1. 比较相邻的前后二个数据,如果前面数据大于后面的数据,就将二个数据交换。
  2. 这样对数组的第0个数据到N-1个数据进行一次遍历后,最大的一个数据就“沉”到数组第N-1个位置。
  3. N=N-1,如果N不为0就重复前面二步,否则排序完成。
实现:
#include<stdio.h>
#include<stdlib.h>
typedef int Item;
#define key(A) (A)
#define less(A,B) (key(A)<key(B))
#define exch(A,B) {Item t=A;A=B;B=t;}
#define compexch(A,B) if(less(B,A)) exch(A,B)
void bubbleSort(Item a[],int l,int r)
{
	int i,j;
	for(i=r;i>l;i--)
		for(j=l+1;j<=i;j++)
		{
			compexch(a[j-1],a[j]);
		}
}
int main(int argc,char *argv[])
{
	int N=atoi(argv[1]);
	int i;
	Item *a=(Item*)malloc(N*sizeof(Item));
	for(i=0;i<N;i++)
	{
		a[i]=1000*(1.0*rand()/RAND_MAX);
		printf("%3d ",a[i]);
	}
	printf("\n");
	bubbleSort(a,0,N-1);
	for(i=0;i<N;i++)
		printf("%3d ",a[i]);
	printf("\n");
	return 0;
}

三 插入排序

插入排序也是一种比较直观的排序方式。可以以我们平常打扑克牌为例来说明,假设我们那在手上的牌都是排好序的,那么插入排序可以理解为我们每一次将摸到的牌,和手中的牌从左到右依次进行对比,如果找到合适的位置则直接插入。具体的步骤为:

  1. 从第一个元素开始,该元素可以认为已经被排序
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
  3. 如果该元素小于前面的元素(已排序),则依次与前面元素进行比较如果小于则交换,直到找到大于该元素的就则停止;
  4. 如果该元素大于前面的元素(已排序),则重复步骤2
  5. 重复步骤2~4 直到所有元素都排好序 。

实现:

#include<stdio.h>
#include<stdlib.h>
typedef int Item;
#define key(A) (A)
#define less(A,B) (key(A)<key(B))
#define exch(A,B) {Item t=A;A=B;B=t;}
#define compexch(A,B) if(less(B,A)) exch(A,B)
void insertSort(Item a[],int l,int r)
{
	int i,j;
	for(i=r;i>l;i--) compexch(a[i-1],a[i]);
	for(i=l+1;i<=r;i++)
	{
		Item v=a[i];
		for(j=i;less(v,a[j-1]);j--)
		{
			a[j]=a[j-1];
		}
		a[j]=v;
	}
}

int main(int argc,char *argv[])
{
	int N=atoi(argv[1]);
	Item *a=(Item*)malloc(N*sizeof(Item));
	for(int i=0;i<N;i++)
		a[i]=1000*(1.0*rand()/RAND_MAX);
	for(int i=0;i<N;i++)
		printf("%3d ",a[i]);
	printf("\n");
	


四 总结

排序算法的运行时间是和算法所执行的比较次数、元素的移动次数或者交换次数成正比的。三种基本排序算法的时间复杂度都是N的平方,但是在复杂度的常数因子上有所不同,所以复杂度总体是插入排序<选择排序<冒泡排序。除此,三种排序算法均不需要额外的空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值