四个简单排序的复习,插入排序,冒泡排序,快速排序,归并排序

最近老师在讲算法分析和设计,数据结构忘了许多,所以借此复习一下。
准备工作:
软件microsoft visual studio
在头文件,我定义了一个结构体,包含数组和长度

#include<stdio.h>
#include<malloc.h>
typedef struct array
{
	int num[20];
	int length = 0;
};
void shows(array* p); 
void insertion_sorting(array* p);
void bubble_sorting(array* p);
void quick_sorting(array* p, int A, int B);
void merge_sort(array* p);

输出函数shows()

//输出函数
void shows(array *p) 
{
	for (int i = 0; i < p->length; i++) {
		printf("%d \t", p->num[i]); //*p解地址,p还可以当做数组名使用
		
	}
	printf("\n"); 
}

main文件,创建实例

	//测试用例的创建和展示
	array *example;
	example = (array*)malloc(sizeof(array));
	if (example == NULL) {
		printf("error");
		return 0;
	}
	int a[] = { 5,9,1,6,11,7,8,13,4 };
	example->length = sizeof(a) / sizeof(a[0]);
//此处sizeof得出的结果是一个unsigned long long 型的数据,所以不能直接进行赋值,需要强制转为int
	for (int i = 0; i < example->length; i++) {
		example->num[i] = a[i];
	}

1.插入排序
思想:从第二个数开始,先用一个哨兵把该数存起来,然后依次与前面的数比较。如果该数比较小,则前一个数向后移一位,出现一个空位,继续往前比较。直到前面的数比较完,或者出现比该数小的数,此轮比较结束,将该数插入空位。
代码如下

//插入排序
void insertion_sorting(array* p) {
	int a;
	for (int i = 1; i < p->length; i++) {
		a = p->num[i];
		for (int j = i-1; j >= 0; ) {
			if (a < p->num[j]) {
				p->num[j+1] = p->num[j];
				j--;
				//a用来暂存num[i],当a应该放在第一位时,则
				if (j < 0) {
					p->num[j+1] = a;
					break;
				}
			}
			else { //如果a应该放在非第一位,则
				p->num[j+1] = a;
				break;
			}
		}
	}
}

2.冒泡排序
思想:每次循环,取第一个数与第二个数比较,将大的数换到后面,然后是第二个数与第三个数比较,依次类推。
代码如下

//冒泡排序
void bubble_sorting(array* p)
{
	int a;
	for (int i = 1; i < p->length; i++) {  //第一层的i是循环次数(因为剩下最后一个数时不用比较,
		//所以length-1次即可),第二层的j是下标,需要和所有未排序的数进行比较,length-i次即可。								
		for (int j = 0; j < p->length - i; j++) {
			if (p->num[j] > p->num[j + 1]) {
				a = p->num[j + 1];
				p->num[j + 1] = p->num[j];
				p->num[j] = a;
			}
		}
	}
}

3.快速排序
思想:取第一个数为标准量criterion,从左右两边出发,如果左边遇到比criterion大的就暂停,右边如果遇到比criterion小的也暂停,如果两边尚未相遇,则交换两边的数。最后将标准量换到分界位置,将数组分为左右两个部分,左边都是比criterion小,右边都比criterion大,然后对左右两边分别继续进行上述步骤。(递归)
代码如下

//快速排序
void quick_sorting(array* p,int A, int B) //AB为数组左右两边端点的下标
{
	if (A >= B) return;

	int criterion = p->num[A];
	int a, b;
	int temp;
	a = A, b = B+1;
	while (a < b)
	{
		do a++; while (p->num[a] < criterion); //从左向右移动,找出所有大于标准(creterion)的
		do b--; while (p->num[b] > criterion);//从右向左移动,找出所有小于标准(creterion)的
		if (a < b) { // 交换位置,使得以creterion为分界线,左边全部小于他,右边全部大于他。
			temp = p->num[b];
			p->num[b] = p->num[a];
			p->num[a] = temp;
		}
	}
	p->num[A] = p->num[b]; //如果ab最后下表相同则这里用ab都可以,如果是b<a,则应该使用下标b
	p->num[b] = criterion;

	quick_sorting(p, A, b-1); // 递归,标准量不计入递归
	quick_sorting(p, b + 1, B);
}

4归并排序
思想:将数组从中间分开,然后对分开的两部分再分,重复上述操作,直到不可再分。然后将分开部分两两比较,重新归并到一起。(递归)
代码如下

//归并排序
void merge_sorting(array *p,int A,int B, int *tmp)
{
	if (A >= B) return;
	int mid = (A + B+1) / 2;

	merge_sorting(p, A, mid-1 ,tmp);
	merge_sorting(p, mid, B,tmp);

	int beg1 = A, end1 = mid - 1, beg2 = mid, end2 = B;
	int index = A;
	while (beg1 <= end1 && beg2 <= end2) { 
		if (p->num[beg1] < p->num[beg2]) {
			tmp[index] = p->num[beg1];  //这三行可以写成一行,如下
			index++;
			beg1++;
		}
		else {
			tmp[index++] = p->num[beg2++];
		}
	}
	while (beg1 <= end1)
	{
		tmp[index++] = p->num[beg1++];
	}
	while (beg2 <= end2)
	{
		tmp[index++] = p->num[beg2++];
	}
	//将归并完的数拷贝回原数组
	for (int i = A; i <= B; i++)
	{
		p->num[i] = tmp[i];
	}
}	
/*
递归的原理
每级函数调用都有自己的变量
每次函数调用都会返回一次
递归函数中位于递归调用之前的语句,按照被调函数的顺序执行
递归函数中位于递归调用之后的语句,按照被调函数相反的顺序执行
(嵌套在最里面的那一层的语句先执行,因为最里面那一层最先返回)
递归函数必须包含能让递归停止调用的语句(return)。
因此每次递归调用的形参都要使用不同的值。
*/
void merge_sort(array* p) {
	int* tmp;
	tmp = (int*)malloc(sizeof(p->num));
	merge_sorting(p, 0, p->length - 1, tmp);
	free(tmp);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值