常见的排序算法C/C++

6 篇文章 0 订阅

目录

一、冒泡排序

二、选择排序(擂台法)

三、插入排序

四、希尔排序(缩小增量排序)

五、快速排序

六、堆排序

七、归并排序(合并排序)

八、递归排序


一、冒泡排序

【思路】冒泡排序算法通过多次比较和交换来实现排序,其排序流程如下

1)对数组中的各数据,依次比较相邻的两个元素的大小;

2)如果前面的数据大于后面的数据,就交换这两个数据。经过第一轮的多次比较排序后,便可把最大的数据排好;

3)再用相同的方法把剩下的数据逐个进行比较,最后便可按照从小到大的顺序排好。

void BubbleSort(int *a, int len) {
	for (int i = 0; i < len - 1; i++)    //进行 len-1 次比较
		for (int j = 0; j < len - i - 1; j++)   //在每次中进行 len-i-1 次比较
			if (a[j] > a[j + 1])      //按升序排序,降序用<
			{
				int temp = a[j + 1];      //交换相邻的两个元素
				a[j + 1] = a[j];
				a[j] = temp;
			}
}

 

 

二、选择排序(擂台法)

【思路】选择排序法在每一步中选取最小值来重新排序。

排序基本流程:

1)首先从原始数组中选择一个最小的数据,将其和位置位于第1个的数据交换;

2)从剩下的n-1个数据中选择次小的一个元素,将其和位于第2个的数据交换;

3)这样不断重复,知道最后两个数据完成交换。

void SelectionSort(int *a, int len) {//升序
	int i, j, k;
	for (i = 0; i < len - 1; i++) {//进行 len-1 次比较
		k = i;
		for (j = i + 1; j < len; j++)
			if (a[j] < a[k]) k = j;//存储下标,不直接交换
		if (k != i) {
			int temp = a[i];
			a[i] = a[k];
			a[k] = temp;
		}
	}
}

void SelectionSort1(int *a, int len) {//降序,按住一个位置不动,循环出一个最大值,好比打擂台
	int i, j, max=0;
	for (i = 0; i < len - 1; i++) {
		max = i;
		for (j = i + 1; j < len; j++) {
			if (a[max] < a[j]) {
				int temp = a[j];
				a[j] = a[max];
				a[max] = temp;
			}
		}
	}
}

以上两个都是选择排序,SelectionSort更高效。

 

 

三、插入排序

【思路】插入排序算法通过比较和插入来实现排序,其排序流程如下:

1)首先对数组的前两个数据进行从小到大排序;

2)将第3个数据与排好序的两个数据比较,将第3个数据插入合适的位置;

3)将第4个数据插入已排好的前3个数据中;

4)不断重复上述过程,直到把最后一个数据插入合适的位置。

void InsertionSort(int *a, int len) {
	int i, j, t;
	for (i = 1; i < len; i++) {
		t = a[i];
		j = i - 1;
		while (j >= 0 && t < a[j]) {
			a[j + 1] = a[j];
			j--;
		}
		a[j + 1] = t;
	}
}

 

 

四、希尔排序(缩小增量排序)

【思路】希尔排序算法严格来说是基于插入排序的思想,Shell排序算法的排序流程如下:

  1. 将有n个元素的素组分为n/2个序列,第1个数据和第n/2+1个数据为1对,等等,依次类推;
  2. 一次循环使每一个序列对排好顺序;
  3. 变为n/4个序列,再次排序;
  4. 不断重复上述过程,随着序列减少直至最后变为1个,完成整个排序。
void ShellSort(int *a, int len) {
	int i, j,  r, temp;
	for (r = len / 2; r >= 1; r /= 2) {//划组排序
         //每一趟采用插入排序
		for (i = r; i < len; i++) {
			temp = a[i];
			j = i - r;
			while (j >= 0 && temp < a[j]) {
				a[j + r] = a[j];
				j -= r;
			}
			a[j + r] = temp;
		}
	}
}

 

 

五、快速排序

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

  1. 首先设置一个分界值,通过分界值将数组分成左右两部分;
  2. 将大于或等于分界值的数据集中到数组右边,小于边界值的数据集中到数组的左边;
  3. 左边和右边的数据可以独立排序。对于左侧的数据,又可以取一个分界值,将该数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数据也可以做类似处理;
  4. 重复以上过程,可以看出这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。
void Quick_Sort(int *a, int begin, int end) {
	if (begin > end)
		return;
	int tmp = a[begin];
	int i = begin;
	int j = end;
	while (i != j) {
		while (a[j] >= tmp && j > i)
			j--;//从右往左找比tmp小的
		while (a[i] <= tmp && j > i)
			i++;//从左往右找比tmp大的
		if (j > i) {
			int t = a[i];
			a[i] = a[j];
			a[j] = t;
		}
	}
	a[begin] = a[i];
	a[i] = tmp;
	Quick_Sort(a, begin, i - 1);
	Quick_Sort(a, i + 1, end);
}

六、堆排序

堆(heap):完全二叉树,父结点的值大于子结点的值。

void print(int a[], int n) {//打印数组
	for (int i = 0; i < n; i++)
		cout << a[i] << " ";
	cout << endl;
}

void HeapSort(int a[], int n) {
	int i, j,  k;
	int t;
	for (i = n / 2 - 1; i >= 0; i--) {//建成大顶堆
		while (2*i+1<n)//第2个结点有右子树
		{
			j = 2 * i + 1;
			if (j + 1 < n) {
				if (a[j] < a[j + 1])//左子树小于右子树,则需要比较右子树
					j++;//序号加1,指向右子树
			}
			if (a[i]<a[j]){//比较i与j为序号的数据
				t = a[i];
				a[i] = a[j];
				a[j] = t; //交换数据
				i = j;//堆被破坏,需要重新调整
			}
			else {//比较左右子节点均大,则堆未破坏,不再需要调整
				break;
			}
		}
	}

	//输出构成的堆
	cout << "原数据构成的堆:";
	print(a, n);

	for (i = n - 1; i > 0; i--) {
		t = a[0];
		a[0] = a[i];
		a[i] = t;
		k = 0;
		while (2 * k + 1 < i) {
			j = 2 * k + 1;
			if (j + 1 < i) {
				if (a[j] < a[j + 1])
					j++;
			}
			if (a[k] < a[j]) {
				t = a[k];
				a[k] = a[j];
				a[j] = t;
				k = j;
			}
			else {
				break;
			}
		}
		cout << "第" << n - i << "步排序:";
		print(a, 10);
	}
}

  

 第1步排序 对应上面第5个树,

 第2步排序 对应上面第8个树,

 第2步排序 对应上面最后个树

 

 

七、归并排序(合并排序)

归并排序:采用分治的思想,将数组(Array)划分为两个子数组(left和right),然后递归(MergeSort)的将每个子数组再进行划分,直到数组中只剩一下一个元素,然后开始排序合并(Merge),直到将所有的子数组合并完成,整个数据就是有序的了。

void print(int a[], int n) {
	for (int i = 0; i < n; i++)
		cout << a[i] << " ";
	cout << endl;
}

void MergeOne(int a[], int b[], int n, int len) {//完成一遍合并的函数
	int i, j, k, s, e;
	s = 0;
	while (s + len < n) {
		e = s + 2 * len - 1;
		if (e >= n) {//最后一段可能少于len个结点
			e = n - 1;
		}
		//相邻有序段合并
		k = s;
		i = s;
		j = s + len;
		while (i < s + len && j <= e) {//如果两个有序表都未结束时,循环比较
			if (a[i] <= a[j])//将较小的数组放到数组b中
				b[k++] = a[i++];
			else
				b[k++] = a[j++];
		}
		while (i < s + len) {//未合并的部分复制到数组b中
			b[k++] = a[i++];
		}
		while (j <= e) {//未合并的部分复制到数组b中
			b[k++] = a[j++];
		}
		s = e + 1;//下一对有序段中左段的开始下标
	}
	if (s < n) {//将剩余的一个有序段从数组a中复制到数组b
		for (; s < n; s++) {
			b[s] = a[s];
		}
	}
}

void MergeSort(int a[], int n) {//合并排序
	int *p;
	int h, count, len, f;

	count = 0;//排序步骤
	len = 1;//有序序列的长度
	f = 0;//标志

	if (!(p = (int *)malloc(sizeof(int)*n))) {//分配内存空间
		cout << "分配内存失败!";
		exit(0);
	}
	while (len < n) {
		if (f == 1) {
			MergeOne(p, a, n, len);//p合并到a
		}
		else
		{
			MergeOne(a, p, n, len);//a合并到p
		}
		len = len * 2;//增加有序序列长度
		f = 1 - f;//使f值在0和1之间切换
		count++;

		cout << "第" << count << "步排序:";
		print(a, n);
	}
	if (f) {//如果进行了排序
		for (h = 0; h < n; h++)//将内存p中的数据复制到数组a中
			a[h] = p[h];
	}
	free(p);//释放内存
}

 

 

八、递归排序

编写sort()函数将一组无序数排列成降序,要求利用递归算法来实现外层循环,主函数中对数据{5,3,7,4,2,9,8,32,54,21,6,43}调用sort()函数实现排序。

void sort(int *x, int n) {
	int j, t;
	if (n == 1)
		return;
	for ( j = 0; j < n; j++)
	{
		if (x[0] < x[j]) {
			t = x[0];
			x[0] = x[j];
			x[j] = t;
		}
	}
	sort(x + 1, n - 1);
}
int main() {
	int a[12] = { 5,3,7,4,2,9,8,32,54,21,6,43 };
	sort(a, 12);
	for (int k = 0; k < 12; k++)
		cout << a[k] << ' ';
	cout << endl;
	return 0;
}

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: C/C++常用手册是程序员日常工作中不可或缺的工具书之一。该手册主要收录了程序员在开发过程中常用的算,以及相应的代码实现。该手册涵盖了诸如数据结构、排序、查找、递归、贪心、动态规划、字符串等算,帮助程序员快速掌握这些算的基本原理和实现方式。简单地说,该手册将算的核心原理和实现细节集中在了一起,兼顾了易懂性和实用性。 随着程序员需求的不断增加,该手册逐渐扩充了更多的算类型。同时,该手册还根据算的不同应用场景进行分类,方便程序员快速查找和使用。例如,程序员可以通过该手册快速了解不同数据结构的原理和实现方,了解常见的时间复杂度和空间复杂度,还可以查找常见的实际问题中的算实现方式。 总的来说,C/C++常用手册是程序员必备的工具之一,帮助程序员提高算的实现能力和解决实际问题的能力,提高程序的效率和质量。 ### 回答2: C/C++常用算手册是一本介绍计算机算的参考手册,主要面向C/C++语言程序员。该手册总结了各种常用的算,包括排序、查找、图论、字符串等。通过该手册的学习,可以让程序员更好地掌握C/C++编程的技巧和方。 该手册中介绍了排序算法,包括冒泡排序、插入排序、选择排序、快速排序、归并排序等。对于不同的排序算法,手册详细介绍了它们的思路和实现方,同时也对它们的时间复杂度和效率进行了分析和比较。 在查找方面,手册介绍了常用的顺序查找和二分查找算,它们可以帮助程序员快速地定位和查找数据。 在图论和字符串方面,手册介绍了很多有用的算,如最短路径算、最小生成树算、字符串匹配算等。这些算可以帮助程序员更好地解决实际问题。 总之,C/C++常用算手册是一本非常实用和有价值的参考书,它可以让程序员掌握更多的C/C++技巧,提高程序员的编程能力和开发效率。 ### 回答3: C/C++ 常用算手册是一本总结了 C/C++ 编程语言中常用的算、数据结构、设计模式等知识的参考书籍。 相对于其他语言,C 和 C++ 语言有着更高的执行效率和更多的编程自由度,也因此被广泛应用于开发高性能、底层的软件程序。在这样的应用场景下,对算和数据结构的掌握显得尤为重要。 C/C++ 常用算手册涵盖了各种基础的算和数据结构,比如排序、查找、链表、树等。同时,它也介绍了一些常用的高级算,比如动态规划、贪心算和回溯算。 此外,该手册还详细说明了面向对象编程领域中常用的设计模式和其实现方式,例如工厂模式、装饰器模式等。 阅读 C/C++ 常用算手册不但能够让读者掌握常用算的实现方,更能提高编程思维和技巧。另外,在实际应用中,编写高效的程序不仅需要算的巧妙运用,更需要细致、严谨的代码风格和设计思路。此时,该手册中丰富的示例代码和编码规范性的讲解也能为读者提供很大的帮助。 总之,C/C++ 常用算手册是一本既实用又深入的参考书,适合广大 C/C++ 开发者和算学习者阅读。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Catherinemin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值