C语言:冒泡排序、选择排序、插入排序、希尔排序、归并排序

目录

1、冒泡排序

2、选择排序

3、插入排序

4、希尔排序

5、归并排序


排序算法图解

1、冒泡排序

判断前后数据大小,如果前者大于后者,则交换。

#include<stdio.h>

#define comp(A,B) (A)>(B)
#define exch(A,B) {int c = A; A = B; B = c;}

int main(void)
{
	int i, j;
	int numb[10];
	for (i = 0; i < 10; i++){
		scanf_s("%d", &numb[i]);
	}

	for (i = 0; i < 10; i++){
		for (j = i + 1; j < 10; j++){
			if (comp(numb[j-1], numb[j]))
				exch(numb[j], numb[j-1]);
		}
	}

	for (i = 0; i < 10; i++){
		printf("%d  ", numb[i]);
	}
}

2、选择排序

每次循环循环找到最小的,与第i个交换。

#include<stdio.h>

#define comp(A,B) (A)>(B)  //如果A>B则返回1,否则为0.
#define exch(A,B) {int c = A; A = B; B = c;}

int main(void)
{
	int i, j, min;
	int numb[10];
	for (i = 0; i < 10; i++){
		scanf_s("%d", &numb[i]);
	}

	for (i = 0; i < 9; i++){
		min = i;
		for (j = i + 1; j < 10; j++){
			if (comp(numb[min], numb[j]))
				min = j;
		}
		exch(numb[i], numb[min]);
	}

	for (i = 0; i < 10; i++){
		printf("%d  ", numb[i]);
	}
}

3、插入排序

#include<stdio.h>

#define comp(A,B) (A)>(B)
#define exch(A,B) {int c = A; A = B; B = c;}

int main(void)
{
	int i, j, a;
	int numb[10];
	for (i = 0; i < 10; i++){
		scanf_s("%d", &numb[i]);
	}

	for (i = 9; i > 0; i--){
		if (comp(numb[i-1], numb[i]))
			exch(numb[i-1], numb[i]);
	}
	for (i = 2; i < 10; i++){
		j = i;
		a = numb[i];
		while (comp(numb[j - 1], a)){
			numb[j] = numb[j - 1];
			j--;
		}
		numb[j] = a;
	}

	for (i = 0; i < 10; i++){
		printf("%d  ", numb[i]);
	}
}

4、希尔排序

      h的值是不可以随意确定的,如果h为1、2、4、8······就会出现有些位置重复判断,有些位置始终不能判断;就好像奇数得不到判断,偶数重复判断,会降低运行效率。

  h为1,4,13,40 ······这样每一个位置都能访问到。

#include<stdio.h>
#define less(A,B) A < B
#define exch(A,B) {int c = A; A = B; B = c;}
int main()
{
	int a[20];
	int i, j, h;
	for (i = 0; i < 20; i++){
		scanf_s("%d", &a[i]);
	}

	for (h = 0; h <= 20 / 3; h = 3 * h + 1);//h1=1; h2=4; h3=13; h4=40
	
	for (h = h; h > 0; h = h / 3){
		printf("%d\n", h);
		for (i = h; i < 20; i++){
			j = i;
			int v = a[i];
			while (j >= h && less(v, a[j - h])){
				a[j] = a[j - h];
				j = j - h;
			}
			a[j] = v;
		}
		
		for (int i = 0; i < 20; i++){
			printf("%-4d", a[i]);
		}
		printf("\n");
	}

}

5、归并排序

    本程序是将a数组作选择排序,b数组作插入排序。最后在归并到c数组中。

    也可以将a作归并排序成一个有序数组,从1个1个开始归并,就有以2个为单位的部分有序,然后2个2个归并,4个4个归并·····直到等于a数组的个数。

/*8.1 归并*/
#include<stdio.h>
#define less(A,B) (A) < (B)
#define exch(A,B) {int c=A; A = B, B = c;}

int main()
{
	int a[5] = { 4,6,2,9,5 };
	int b[10] = { 0,5,9,3,1,7,2,13,3,6 };
	int c[15];
	int i, j, k;

	/*选择排序对a*/
	for (i = 0; i < 5; i++){
		int numb = i;
		for (j = i + 1; j < 5; j++)
		{
			if (less(a[j],a[numb]))
				numb = j;
		}
		exch(a[i], a[numb]);
	}

	printf("a: ");
	for (i = 0; i < 5; i++){
		printf("%d  ", a[i]);
	}
	printf("\n");
	
	/*插入排序对b*/
	for (i = 9; i > 0; i--){
		if (less(b[i], b[i - 1]))
			exch(b[i], b[i - 1]);
	}
	for (i = 2; i < 10; i++){
		j = i;
		int numb = b[i];
		while (less(numb, b[j - 1])){
			b[j] = b[j - 1];
			j--;
		}
		b[j] = numb;
	}

	printf("b: ");
	for (i = 0; i < 10; i++){
		printf("%d  ", b[i]);
	}
	printf("\n");

	//两个数组已经有序,再将其排在c中
	for (k = 0, i = 0, j = 0; k < 15; k++){
		if (i == 5)
		{
			c[k] = b[j++];
			continue;
		}
		if (j == 10)
		{
			c[k] == a[i++];
			continue;
		}
		c[k] = less(a[i], b[j]) ? a[i++]: b[j++];
	}

	printf("c: ");
	for (i = 0; i < 15; i++){
		printf("%d  ", c[i]);
	}
}

 或者为以下这种

/*8.3 归并图
 自顶向下归并排序     自底向上归并排序
3 2 4 6 9 1 5 0 8 7   3 2 4 6 9 1 5 0 8 7
2 3****************     2 3****************
****4 6************     ****4 6************
2 3 4 6************     ********1 9********
********1 9********     ************0 5****
************0 5****     ****************7 8
************0 1 5 9     2 3 4 6************
0 1 2 3 4 5 6 9****     ********0 1 5 9 7 8
****************7 8     0 1 2 3 4 5 6 9****
0 1 2 3 4 5 6 7 8 9     0 1 2 3 4 5 6 7 8 9
*/


#include<stdio.h>

/*对数组部分排序*/
void Merge(int a[], int head, int m, int end);

/*自顶向下归并排序,把数组分区,逐个排序*/
void MergeSortA(int a[], int head, int end);

/*自底向上归并排序,把数组分区,逐个排序*/
void MergeSortB(int a[], int head, int end);

int main()
{
	int a[10] = { 3,2,4,6,9,1,5,0,8,7 };
	int b[10] = { 3,2,4,6,9,1,5,0,8,7 };
	MergeSortB(a, 0, 9);
	MergeSortA(b, 0, 9);
	for (int i = 0; i < 10; i++)
		printf("%d  ", a[i]);
}

void Merge(int a[], int head, int m, int end)
{
	if (head >= end)
		return;
	int c[10] = { 0 };/*注意数组的大小*/
	int i = head, j = m + 1, t;
	for (t = 0; t < end - head + 1; t++)
	{
		if (i == m + 1)
		{
			c[t] = a[j++];
			continue;
		}
		if (j == end + 1)
		{
			c[t] = a[i++];
			continue;
		}
		c[t] = a[i] < a[j] ? a[i++] : a[j++];
	}

	i = head;
	for (t = 0; t < end - head + 1; t++)
	{
		a[i++] = c[t];
	}
}

void MergeSortA(int a[], int head, int end)
{
	int m = (end + head) / 2;
	if (head >= end)
		return;
	MergeSortA(a, head, m);
	MergeSortA(a, m + 1, end);
	Merge(a, head, m, end);

}

void MergeSortB(int a[], int head, int end)
{
	int i, m;
	for (m = 1; m < end; m = m * 2)
	{
		for (i = 0; i < end; i = i + m * 2)
		{
			if (i + m * 2 - 1 < end)
				Merge(a, i, i + m - 1, i + m * 2 - 1);
			else
			{
				if (i + m < end)
					Merge(a, i, i + m - 1, end);
				else
					Merge(a, i, (i + end) / 2, end);
			}		
		}
	}
}

 不去打扰便是最好的守护!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值