【数据结构】排序详解(希尔排序,快速排序,堆排序,插入排序,选择排序,冒泡排序)

目录

0. 前情提醒:

1. 插入排序

1.1 基本思想:

1.2 直接插入排序

 实现步骤:

 动图演示:

 特性总结:

 代码实现:

1.3 希尔排序(缩小增量排序)

基本思想:

步骤演示:

特性总结:

代码实现:

2. 交换排序

2.1 基本思想:

2.2 冒泡排序

特性总结:

代码实现:

2.3 快速排序

3.选择排序

3.1 基本思想:

3.2 直接选择排序

步骤思路:

动图演示: 

特性总结:

代码实现:

3.3 堆排序

代码实现:


0. 前情提醒:

下面的所有代码实现均为升序

1. 插入排序

1.1 基本思想:

把待排序的记录按其关键码值的大小逐个插入到一个已经排序好的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。

1.2 直接插入排序
 实现步骤:

当插入第i(i>=1)各元素时,前面的array[0],array[1],......,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],......的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移

 动图演示:

 特性总结:
  1. 元素集合越接近有序,直接插入排序算法的时间效率越高
  2. 时间复杂度:O(N^2)
  3. 空间复杂度:O(1),它是一种稳定的排序算法
  4. 4.稳定性:稳定
 代码实现:
void InsertSort(int* a, int n) {
	for (int i = 0; i < n; i++) {
		int m = a[i];
		int end = i;
		while (end > 0 && a[end - 1] > m) {
			a[end] = a[end - 1];
			end--;
		}
		a[end] = m;
	}
}
1.3 希尔排序(缩小增量排序)
基本思想:

先选定一个整数,把待排序的文件中所有(n个)记录分成(n/gap)个组,所有距离为gap的记录分在同一个组,并对每个组内的记录进行排序。然后去gap=gap/2,重复上述分组和排序的工作。当到达gap=1时,所有记录在统一组内排好序(gap=1时就是直接插入排序,gap>1时属于预排序)。

步骤演示:

特性总结:
  1. 希尔排序是对直接插入排序的优化
  2. 当gap>1时都是预排序,目的是让数组更接近有序。当gap==1时,数组已经接近有序,这样排序就会很快。这样整体而言,可以达到优化的效果
  3. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在不同书上给出的希尔排序的时间复杂度都不一样
代码实现:
void ShellSort(int* a, int n) {
	int gap = n;
	while (gap > 1) {
		gap = gap / 3 + 1;
		for (int i = 0; i < n; i++) {
			int m = a[i];
			int end = i;
			while (end > 0 && a[end - gap] > m) {
				a[end] = a[end - gap];
				end -= gap;
			}
			a[end] = m;
		}
	}
}

2. 交换排序

2.1 基本思想:

所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向前部移动

2.2 冒泡排序

左边大于右边交换,一趟排下来最大的在右边

特性总结:
  1. 冒泡排序是一种非常容易理解的排序
  2. 时间复杂度:O(N^2)
  3. 空间复杂度:O(1)
  4. 稳定性:稳定
代码实现:
void BubbleSort(int* a, int n) {
	for (int i = 0; i < n; i++) {
		int k = 1;
		for (int j = 0; j < n-i-1; j++) {
			if (a[j] > a[j + 1]) {
				k = 0;
				int x = a[j];
				a[j] = a[j + 1];
				a[j + 1] = x;
			}
		}
		if (k) {
			break;
		}
	}
}
2.3 快速排序

快速排序较为复杂,想了解请点击-----》快速排序

3.选择排序

3.1 基本思想:

每一次从待排序的数据元素中选出一个最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完

3.2 直接选择排序
步骤思路:
  • 在元素array[i]--array[n-1]中选择关键码最小(或最大)的数据元素
  • 若它不是这组元素中最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换
  • 在剩余的array[i]--array[n-2](array[i+1]--array[n-1])集合中,重复上述步骤,直到集合剩余1个元素
动图演示: 

特性总结:
  1. 思路很好理解,但效率不好,实际很少应用,主要具有教学意义
  2. 时间复杂度:O(N^2)
  3. 空间复杂度:O(1)
  4. 稳定性:不稳定
代码实现:
void SelectSort(int* a, int n) {
	for (int i = 0; i < n; i++) {
		int min = n - 1;
		for (int j = i; j < n; j++) {
			if (a[min] > a[j]) {
				min = j;
			}
		}
		swap(&a[min], &a[i]);
	}
}
3.3 堆排序

堆排序(HeapSort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据,利用堆中某个节点的值总是不大于或不小于其父节点的值的特性。注意:升序建大堆,降序建小堆

代码实现:
void AdjustDwon(int* a, int n, int root) {
	int i = 2 * root + 1;
	if (i < n - 1 && a[i] < a[i + 1]) {
		i++;
	}
	if (i < n && a[root] < a[i]) {
		swap(&a[root], &a[i]);
		AdjustDwon(a, n, i);
	}
}
void HeapSort(int* a, int n) {
//建堆
	for (int i = (n - 1 - 1) / 2; i >= 0; i--) {
		AdjustDwon(a, n, i);
	}
	while (n>1) {
		swap(&a[0], &a[n-1]);
		n--;
		AdjustDwon(a, n, 0);
	}
}

  • 25
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
简单选择排序是一种基于比较和交换的排序算法。它通过n-i次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并与第i个记录交换位置。 简单选择排序算法步骤如下: 1. 定义一个变量min来表示当前未排序部分中的最小元素的下标。 2. 通过两层循环,外层循环从第一个元素到倒数第二个元素,内层循环从外层循环的下一个元素到最后一个元素,找到未排序部分中的最小元素的下标。 3. 如果找到的最小元素不在当前位置,则将最小元素与当前位置的元素交换位置。 4. 重复步骤2和步骤3,直到所有元素都被排序。 简单选择排序的性能分析: - 时间复杂度:简单选择排序的时间复杂度为O(n^2),其中n是待排序序列的长度。这是因为每一趟都需要在剩余的未排序部分中寻找最小元素,所以总共需要进行n-1趟比较和交换操作。 - 空间复杂度:简单选择排序的空间复杂度为O(1),因为只需要使用常数个额外的变量来存储最小元素的下标。 - 稳定性:简单选择排序是一种不稳定的排序算法,因为在交换元素的过程中可能会改变相同元素的相对位置。 总结来说,简单选择排序是一种简单但效率较低的排序算法,适用于数据规模较小的情况。它的主要思想是通过不断找到未排序部分中的最小元素,并将其放到已排序部分的末尾,从而逐步完成排序。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [数据结构排序(Sort)【详解】](https://blog.csdn.net/Real_Fool_/article/details/114692744)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值