排序算法

这里列举了几种常见的排序算法:

1.冒泡排序

2.插入排序

3.选择排序

4.快速排序

5.归并排序

这里仅仅是介绍这几种算法的思路,并不会深入地分析这几种算法。《算法导论》对这几种都进行了深入地分析和扩展。如果希望对这几种排序算法有更深入的了解,大家可以去阅读《算法导论》相关的内容。

 

1.   冒泡排序

这个算法会比较前后相邻的两个元素,如果后面的元素比前面小就交换两个元素的位置(假设这里是从小到大排序,从大到小则反之)。假设这里有N个元素,如果我们从第一个元素开始比较,那么第一个元素和第二个元素较大的一个会被放到第二个元素的位置上。接着,比较第二个元素和第三个元素之后,第一个、第二个和第三个之中最大的元素会被放到第三个元素的位置上。以此类推,比较到第N个元素之后,最大的元素会放到第N个元素的位置上。

(盗用百度图片一张,哈哈。)


一轮比较下来,最大的元素会被放到最后的位置(也许这就是这个算法名字的由来)。由于最大的元素被放到最后的位置,所以下一轮就不用比较最后的元素,只要比较N-1个元素。以此类推,每一轮比较都会比上一轮少比较一个元素,因为上一轮比较的最后一个元素位置肯定是正确的。

下面是代码

#include <stdio.h>

void bubbleSort(int array[],int len){
	int i,j;
	for(i=0;i<len-1;i++){
		for(j=0;j<len-i-1;j++){
			if(array[j]>array[j+1]){
				int temp=array[j];
				array[j]=array[j+1];
				array[j+1]=temp;
			}
		}
	}
}

void printArray(int array[],int len){
	int i;
	for(i=0;i<len;i++)
		printf("%d ",array[i]);
	printf("\n");
}


int main(){
	int array[]={9,5,3,4,6,8,7,1,2,0};
	int len=sizeof(array)/sizeof(array[0]);
	printf("before bubble sort\n");
	printArray(array,len);
	printf("after bubble sort\n");
	bubbleSort(array,len);
	printArray(array,len);
	return 0;
}


 

2.   插入排序

插入排序类似整理扑克牌,将一张张新的扑克牌插入到已整理好的牌堆之中。很简单的思路。

(持续盗图中…)


代码如下

#include <stdio.h>

void insertSort(int array[],int len){
	int i,j;
	for(i=1;i<len;i++){
		int tmp = array[i];
		for(j=0;j<i;j++){
			if(tmp<array[j])
				break;
		}
		for(;j<=i;j++){
			int swap = tmp;
			tmp = array[j];
			array[j] = swap;
		}
	}
}

void printArray(int array[],int len){
	int i;
	for(i=0;i<len;i++)
		printf("%d ",array[i]);
	printf("\n");
}


int main(){
	int array[]={9,5,3,4,6,8,7,1,2,0};
	int len=sizeof(array)/sizeof(array[0]);
	printf("before insert sort\n");
	printArray(array,len);
	printf("after insert sort\n");
	insertSort(array,len);
	printArray(array,len);
	return 0;
}


3.   选择排序

在这个算法中,我们先找到所有元素中最小的元素,然后和第一个元素进行交换。这样第一个元素就已经排好序,所以我们不用管第一个元素了。那么从剩下的元素中找到最小的元素(也就是第二小的元素,最小的元素已经在第一个位置上了)跟第二元素交换位置。这样循环到最后一个元素就可以将数组从小到大排序好。

#include <stdio.h>

void selectSort(int array[],int len){
	int i,j;
	int index = 0;
	for(i=0;i<len-1;i++){
		index = i;
		for(j=i;j<len;j++){
			if(array[j]<array[index])
				index = j;
		}
		int swap = array[index];
		array[index] = array[i];
		array[i] = swap;
	}
}

void printArray(int array[],int len){
	int i;
	for(i=0;i<len;i++)
		printf("%d ",array[i]);
	printf("\n");
}


int main(){
	int array[]={9,5,3,4,6,8,7,1,2,0};
	int len=sizeof(array)/sizeof(array[0]);
	printf("before select sort\n");
	printArray(array,len);
	printf("after select sort\n");
	selectSort(array,len);
	printArray(array,len);
	return 0;
}


4.   快速排序

快速排序主要是使用了分治思想,选择一个元素作为一个分隔元素。将数组划分成左右两个子数组,左边子数组元素的值都比分隔元素小,右边子数组的值都比分隔元素大。以此递归,对左右两个子数组再进行分割,直到子数组只有一个元素的时候,该数组已经从小到大排序好了。这样做的好处就是避免了很多重复的判断。由于左右两个数组一个比某个值小,一个比某个值小,这两个数组的值就不用相互比较了。网上博客常见的是用数组第一个元素作为分割元素。

下面是参考《算法导论》写出的代码。代码中是使用数组的最后一个元素作为分割元素的…

#include <stdio.h>

int partition(int array[],int start,int end){
	int key = array[end];
	int i = start - 1;
	int j;
	int swap;
	for(j=start;j<end;j++){
		if(array[j]<=key){
			i++;

			swap = array[i];
			array[i] = array[j];
			array[j] = swap;
		}
	}

	swap=array[i+1];
	array[i+1]=array[end];
	array[end]=swap;

	return i+1;
}

void quickSort(int array[],int start,int end){
	if(start<end){
		int mid  = partition(array,start,end);
		quickSort(array,start,mid-1);
		quickSort(array,mid+1,end);
	}
}

void printArray(int array[],int len){
	int i;
	for(i=0;i<len;i++)
		printf("%d ",array[i]);
	printf("\n");
}


int main(){
	int array[]={9,5,3,4,6,8,7,1,2,0};
	int len=sizeof(array)/sizeof(array[0]);
	printf("before bubble sort\n");
	printArray(array,len);
	printf("after bubble sort\n");
	quickSort(array,0,len-1);
	printArray(array,len);
	return 0;
}


5.   归并排序

归并排序的核心操作是将两个排好序的合并成一个排好序的数组。这里可以使用递归将单个元素一步步合并成一个大的数组。这就是归并排序的大体思路。下面是代码实现。

PS: 《算法导论(第三版)》中没有专门讲归并排序,它的介绍在第2章的2.3.1小节中

#include <stdio.h>

void merge(int array[],int start,int mid,int end,int temp[]){
	int i=start,j=mid+1;
	int k=0;
	while(i<=mid && j<=end){
		if(array[i]<=array[j]){
			temp[k++]=array[i++];
		}
		else{
			temp[k++]=array[j++];
		}
	}

	while(i<=mid){
		temp[k++] = array[i++];
	}

	while(j<=end){
		temp[k++] = array[j++];
	}

	for(i=0;i<k;i++){
		array[start+i] = temp[i];
	}
}


void mergeSort(int array[],int start,int end,int temp[]){
	if(start<end){
		int mid = (start+end) / 2;
		mergeSort(array,start,mid,temp);
		mergeSort(array,mid+1,end,temp);
		merge(array,start,mid,end,temp);
	}
}

void printArray(int array[],int len){
	int i;
	for(i=0;i<len;i++)
		printf("%d ",array[i]);
	printf("\n");
}


int main(){
	int array[]={9,5,3,4,6,8,7,1,2,0};
	int temp[10];
	int len=sizeof(array)/sizeof(array[0]);
	printf("before merge sort\n");
	printArray(array,len);
	printf("after merge sort\n");
	mergeSort(array,0,len-1,temp);
	printArray(array,len);
	return 0;
}


 

 

     

 

 

 

 

 

 

 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值