冒泡排序和快速排序(C语言实现)

冒泡排序和快速排序(C语言实现)

冒泡排序

冒泡排序的原理是:从左到右,相邻元素进行比较。每次比较一轮,就会找到序列中最大的一个或最小的一个。这个数就会从序列的最右边冒出来。

以从大到小排序为例,第一轮比较后,所有数中最小的那个数就会浮到最右边;第二轮比较后,所有数中第二小的那个数就会浮到倒数第二个位置……就这样一轮一轮地比较,最后实现从大到小排序。

例如:5,2,3,4,1(从大到小排列)

第一轮:

(1)第一次:5与2 比较5>2就不用交换,此时的顺序为 5,2,4,3,1

(2)第二次 :2与3 比较2<3,此时交换2和3的位置,交换后顺序为 5,3,2,4,1

(3)第三次 :2与4比较2<4,此时交换2和4的位置,交换后顺序为 5,3,4,2,1

(4)第四次 :2与1比较2>1,此时位置不变。

第二轮:

(1)第一次 :5与3比较5>3,不用交换,此时顺序为 5,3,4,2,1

(2)第一次 :3与4比较3<4,交换3与4的位置,此时顺序为 5,4,3,2,1

(3)第三次 :3与2比较3>2,不用交换位置,此时顺序为 5,4,3,2,1

因为最后一个数在第一轮比较后已经是最小的数了,所以不用与已经排好序的数比较(此时只有最后一个数是已经拍好序的)。

第三轮:

(1)第一次 :5与4比较5>4,不用交换位置,此时顺序为 5,4,3,2,1

(2)第二次 :4与3比较4>3,不用交换位置,此时顺序为 5,4,3,2,1

因为最后一个数在第一轮比较后已经是最小的数了,所以不用与已经排好序的数比较(此时最后两个个数是已经拍好序的)。

在本次循环发现所有的数都没有交换位置所以此时已经完成了排序,就可以跳出循环。

代码实现:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void BubbleSort(int a[],int n,int *b){ //定义冒泡排序的函数:参数整形数组a[],数组长度n,记录比较轮数的整形指针 
	int i;//比较的次数 
	int j;//每轮比较的轮数 
	int temp;//交换数据时用于存放中间数据
	int  flag;//标志,用于记录本轮排序是否交换了数据 
	for(i=0; i< n-1;i++){//比较n-1轮 
		flag=0; //每轮比较前将标志置为0,表示为交换 
		for(j=0;j<n-1-i;j++){//没比较一轮就可以至少将一个数据放到正确的位置
		                    //所以第i轮比较时只用比较n-1-i次 
			if(a[j]<a[j+1]){//判断j号数据是否小于j+1号数据 
				temp=a[j]; //若if中条件为真,进行数据交换 
				a[j]=a[j+1];
				a[j+1]=temp;
				flag=1;    //交换数据后将交换数据的标志置为1 
			}
		}
		*b=*b+1;  //每轮比较后比较的轮数加1 
		if(flag==0)//每轮比较完成后判断次轮是否交换过数据 
			return;//若没有交换数据,说明排序完成,退出函数 
	}
} 
void display(int a[],int n){//定义输出数组数据的函数:参数(整形数组a[],数组长度n) 
	int i;
	for(i=0;i<n;i++){
	printf("%d\t",a[i]);
	if((i+1)%5==0){
		printf("\n\t");
	}
	}
	printf("\n");
} 
int main(int argc, char *argv[]) {
	int count=0;
	int a[]={5,2,6,15,12,18,3,66,19,20,23};
	printf("排序前:");
	display(a,sizeof(a)/sizeof(a[0]));//a[0]是int型, 占4字节, 所以总的字节数除以4等于元素的个数
	BubbleSort(a,sizeof(a)/sizeof(a[0]),&count); 
	printf("排序后:"); 
	display(a,sizeof(a)/sizeof(a[0]));
	printf("共进行了%d循环",count);
	return 0;
}
执行结果

在这里插入图片描述

快速排序

基本思想:

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

快速排序算法通过多次比较和交换来实现排序,其排序流程如下:

(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。

(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。

(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。

(4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。

假设一开始序列a[i]是:5,3,7,6,4,1,0,2,9,10,8。

此时,key=5,low=1,high=11,从后往前找,第一个比5小的数是[8]=2,因此序列为:2,3,7,6,4,1,0,5,9,10,8。

此时low=1,high=8,从前往后找,第一个比5大的数是a[3]=7,因此序列为:2,3,5,6,4,1,0,7,9,10,8。

此时,low=3,high=8,从第8位往前找,第一个比5小的数是x[7]=0,因此:2,3,0,6,4,1,5,7,9,10,8。

此时,low=3,high=7,从第3位往后找,第一个比5大的数是a[4]=6,因此:2,3,0,5,4,1,6,7,9,10,8。

此时,low=4,high=7,从第7位往前找,第一个比5小的数是a[6]=1,因此:2,3,0,1,4,5,6,7,9,10,8。

此时,low=4,high=6,从第4位往后找,直到第6位才有比5大的数,这时,low=high=6,key成为一条分界线,它之前的数都比它小,之后的数都比它大,对于前后两部分数,可以采用同样的方法来排序.

代码实现:
#include <stdio.h>
#include <stdlib.h>
int Partition(int a[],int low ,int high){
	int pivot=a[low];//选择一个标准数据 
	while(low<high){//执行循环直到high与low相遇是结束循环 
		while(low<high&&a[high]>=pivot)//从右往左找一直找到比基准数据小的数据跳出循环 
			high--;//没有找到比基准数据小的数据时就向前移动 
		a[low]=a[high];//找到比基准数据小时就将该数据赋给左边a[low]; 
		while(low<high&&a[low]<=pivot)//从左往右找一直找到比基准数据大的数据跳出循环 
			low++;//没有找到比基准数据大的数据时就向后移动
		a[high]=a[low];//找到比基准数据大时就将该数据赋给左边a[high];
	}
	a[low]=pivot;//跳出循环时low=high,此时low或者high就是基准数据的正确位置 
	return low;//返回基准数据的正确位置 
} 
void QuickSort(int a[],int low,int high){
	if(low<high){//判断排序是否完成(当high=low说明排序完成) 
		int pivotpos=Partition(a,low,high);//记录上次排序完成时基准位置,作为分段的表准 
		QuickSort(a,low,pivotpos-1);//将上次排序后基准位置的左边数据进行排序 
		QuickSort(a,pivotpos+1,high);//对右边进行排序 
	}
}

void display(int a[],int n){//定义输出数组数据的函数:参数(整形数组a[],数组长度n) 
	int i;
	for(i=0;i<n;i++){
	printf("%d\t",a[i]);
	if((i+1)%5==0){
		printf("\n\t");
	}
	}
	printf("\n");
} 
int main(int argc, char *argv[]) {
	int a[]={5,2,6,15,12,18,3,66,19,20,23};
	printf("排序前:");
	display(a,sizeof(a)/sizeof(a[0]));//a[0]是int型, 占4字节, 所以总的字节数除以4等于元素的个数
	QuickSort(a,0,sizeof(a)/sizeof(a[0])-1);
	printf("排序后:"); 
	display(a,sizeof(a)/sizeof(a[0]));
}
运行结果:

在这里插入图片描述

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值