首页 > 其他分享 >每日回顾:简单用C写 直接插入排序、希尔排序

每日回顾:简单用C写 直接插入排序、希尔排序

时间:2024-10-16 21:52:10浏览次数:8  
标签:tmp end int 插入排序 gap 希尔 排序 复杂度

直接插入排序

直接插入排序(Straight Insertion Sort)是一种简单直观的排序算法。它的基本思想是将未排序的数据插入到已排序的序列中。

大致思想:

使用 2 个数组下标指针 end、i 模拟数组元素逐个进行插入的过程;

i 每递增一次,代表数组新插入一个元素。在这次循环中,end 将逐渐递减比较已有元素与新插入元素的大小,

如果新插入元素小 :直接向后挪动覆盖(在此之前,被覆盖的元素已提前使用 tmp 存储),最后 end 会停在合适位置的前一个下标处,将 tmp 放回去

如果新插入元素大:升序情况下,无须再进行比较

//直接插入排序
void InsertSort(int* a, int n) {
	//从第二个元素插入开始
	for (int i = 1; i < n; i++) {
		int tmp = a[i];
		int end = i - 1;
		while (end >= 0) {
			//升序
			if (a[end] > tmp) {
				//挪动覆盖之前,保存 a[i]
				a[end + 1] = a[end];
				end--;
			}
			else {	//如果 a[end] 小于等于 tmp,说明之前的都小于等于 tmp
				break;
			}
		}
		a[end + 1] = tmp;
	}
}

时间复杂度

直接插入排序的时间复杂度,取决于数组长度和元素的交换次数;

前者消耗的时间避免不了,那么如果数组本来有序,无须比较的情况下,时间复杂度为 O(n);

如果数组是逆序,时间复杂度为 O(n^2)

空间复杂度

原地修改,空间复杂度 O(1)

稳定性

直接插入排序没有元素换来换去的情况,稳定

希尔排序

希尔排序(Shell Sort)是插入排序的一种更高效的改进版本。希尔排序由Donald Shell于1959年提出,它通过将原始数据分成多个子序列,分别对每个子序列进行直接插入排序,从而提高效率。

大致思想:

预排序-->接近有序

增量 gap :将待排序数据按照间隔 gap 个元素,分成多个子序列,对子序列进行直接插入排序

当 gap 增量逐渐递减到 1 ,就是直接插入排序;在已经接近有序的情况下,直接插入排序的效率还是比较好的

版本一:

//希尔排序1
void ShellSort_1(int* a, int n) {
	int gap = n;
	//控制 gap 递减
	while (gap > 1) {	//不能用 gap >= 1 ,否则会死循环
		gap = gap / 3 + 1;	//保证 gap 最后一次一定是 1
		for (int j = 0; j < gap; j++) {	//每次循环排好一组 gap 的数据
			//直接插入排序
			for (int i = j; i < n - gap; i += gap) {
				int end = i;
				int tmp = a[end + gap];
				while (end >= 0) {
					if (a[end] > tmp) {
						a[end + gap] = a[end];
						end -= gap;
					}
					else {
						break;
					}
				}
				a[end + gap] = tmp;
			}
		}
	}
}

版本二:

//希尔排序2
void ShellSort_2(int* a, int n) {
	int gap = n;
	while (gap > 1) {
		gap = gap / 3 + 1;
		//多组数据并排
		for (int i = 0; i < n - gap; i++) {
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0) {
				if (a[end] > tmp) {
					a[end + gap] = a[end];
					end -= gap;
				}
				else {
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}
}

区别

版本一、二的区别在于,版本一是将每组子序列独立地排序;版本二则是比较巧妙,多组子序列并行排序,只需要按顺序遍历一遍数组就可以

时间复杂度

希尔排序的时间复杂度取决于 gap 增量的大小,要详细分析很困难,了解即可

最好情况:当增量序列选择得当时,时间复杂度可以达到 O(n*log⁡n)

平均情况:时间复杂度通常在 O(n^1.3)到 O(n^1.7)之间

最坏情况:时间复杂度为 O(n^2)

空间复杂度

原地修改,空间复杂度 O(1)

稳定性

不稳定,因为可能会有相同元素处于不同的子序列中,发生交换时可能导致不稳定

标签:tmp,end,int,插入排序,gap,希尔,排序,复杂度
From: https://blog.csdn.net/kaneki_11/article/details/142964127

相关文章

  • 数据结构八大排序的java实现
    冒泡排序package排序;importjava.util.Arrays;publicclassBubbleSort{   publicstaticvoidmain(String[]args){      int[]arr={5,7,4,2,0,3,1,6};      sort(arr);      System.out.println(Arrays.toString(arr));   }......
  • 深度解析计数排序:原理、特性与应用
    目录......
  • python如何将list排序
    python提供了对list排序的两种方法1、使用list内建函数sort排序list.sort(key=None,reverse=False)eg:In [57]: l=[27,47,3,42,19,9]In [58]: l.sort()In [59]: lOut[59]: [3, 9, 19, 27, 42, 47]上面这种是直接对l列表里面的元素排序,sort()函数还提供......
  • C++ 排序算法(选择、冒泡、插入)
    八、选择排序(从小到大): 选择排序的基本思想是:每一趟从待排序的数据中,通过“打擂台”比较选出最小元素,放在这些数据的最前面。这样,第一趟把n个数中(第1个到第n个)最小的放在第一个位置,第二趟把剩余的n-1个数中(第2个到第n个)最小的放在第二个位置,第三趟把剩余的n......
  • 【数据结构】:破译排序算法--数字世界的秩序密码(二)
    文章目录前言一.比较排序算法1.`BubbleSort`冒泡排序1.1.冒泡排序原理1.2.冒泡排序过程1.3.代码实现1.4.复杂度和稳定性2.`QuickSort`快速排序2.1递归快速排序2.1.1.递归快速排序原理2.1.2.递归快速排序过程2.1.3.代码实现2.2.非递归快速排序2.2.1.非递归快速排序原......
  • 合并两个排序的链表
    输入两个链表,并将它们的值按照递增的顺序合并成一个新的链表。题目要求如下:  我们可以创建两个新的链表,其中一个作为中间变量来存储合并后的链表,另一个链表记录中间链表并作为返回值返回。代码如下:/***structListNode{* intval;* structListNode*next;*}......
  • 堆排序题解
    给定一个整数序列,请按非递减序输出采用堆排序的各趟排序后的结果。输入格式:测试数据有多组,处理到文件尾。每组测试数据第一行输入一个整数n(1≤n≤100),第二行输入n个整数。输出格式:对于每组测试,输出若干行,每行是一趟排序后的结果,每行的每两个数据之间留一个空格。输入样例......
  • Java 列表元素自定义排序
    在Java开发过程中,有时会遇到需要对列表中元素进行自定义的排序。这样的排序往往不能由元素本身的特性(比如字符串长度、首字母顺序)判断,需要自己指定顺序。比如对汉字的数字进行排序,他们的字符串长度都为1,首字母顺序也不能得到预期的结果,因此需要自定义排序。以下是示例代码:p......
  • 代码随想录训练营第63天|拓扑排序
    117.软件构建#include<iostream>#include<vector>#include<queue>#include<unordered_map>usingnamespacestd;intmain(){intm,n,s,t;cin>>n>>m;vector<int>inDegree(n,0);//记录每个文件的入度......
  • 912.排序数组
    这一题我们要用归并排序的方法归并排序1)整体就是一个简单递归,左边排好序、右边排好序、让其整体有序2)让其整体有序的过程里用了排外序方法3)利用master公式来求解时间复杂度4)归并排序的实质时间复杂度O(N*logN),额外空间复杂度O(N)912.排序数组给你一个整数数组 nums,......