数据结构(排序)

文章目录


一、排序概念

1.1 概念

  • 排序:所谓排序,就是使⼀串记录,按照其中的某个或某些关键字的⼤⼩,递增或递减的排列起来的操作。

1.2 常见的排序算法

二、实现常见的排序算法

2.1 直接插入排序

复制代码
void InsertSort(int* arr, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int end = i;
		int tmp = arr[end + 1];
		while (end >= 0)
		{
			if (arr[end] > tmp)
			{
				arr[end + 1] = arr[end];
				end--;
			}
			else
			{
				break;
			}
			arr[end + 1] = tmp;
		}
	}
}
  • 当插⼊第 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)

2.2 希尔排序

复制代码
void ShellSort(int* arr, int n)
{
	int gap = n;
	while (gap > 1)
	{
		int gap = gap / 3 + 1; //保证最后一次的 gap 是 1。
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = arr[end+gap];
			while (end >= 0)
			{
				if (arr[end] > tmp)
				{
					arr[end + gap] = arr[end];
					end-=gap;
				}
				else
				{
					break;
				}
				
			}
			arr[end + gap] = tmp;
		}
	}
}
  • 希尔排序法⼜称缩⼩增量法。希尔排序法的基本思想是:先选定⼀个整数(通常是gap = n/3+1),把待排序⽂件所有记录分成各组,所有的距离相等的记录分在同⼀组内,并对每⼀组内的记录进⾏排序,然后gap=gap/3+1得到下⼀个整数,再将数组分成各组,进⾏插⼊排序,当gap=1时,就相当于直接插⼊排序。
  • 它是在直接插⼊排序算法的基础上进⾏改进⽽来的,综合来说它的效率肯定是要⾼于直接插⼊排序算法的:


希尔排序的特性总结

  1. 希尔排序是对直接插⼊排序的优化。
  2. 当 gap > 1 时都是预排序,⽬的是让数组更接近于有序。当 gap == 1 时,数组已经接近有序 的了,这样就会很快。这样整体⽽⾔,可以达到优化的效果。
希尔排序的时间复杂度计算

希尔排序的时间复杂度估算:
外层循环:
外层循环的时间复杂度可以直接给出为: O (log 2 n ) 或者 O (log 3 n ) ,即 O (log n )
内层循环:

假设⼀共有n个数据,合计gap组,则每组为n/gap个;在每组中,插⼊移动的次数最坏的情况下为
⼀共是gap组,因此:
总计最坏情况下移动总数为:

gap取值有(以除3为例):n/3 n/9 n/27 ...... 2 1
• 当gap为n/3时,移动总数为:
• 当gap为n/9时,移动总数为:
• 最后⼀躺,gap=1即直接插⼊排序,内层循环排序消耗为n

因此,希尔排序在最初和最后的排序的次数都为n,即前⼀阶段排序次数是逐渐上升的状态,当到达某⼀顶点时,排序次数逐渐下降⾄n,⽽该顶点的计算暂时⽆法给出具体的计算过程

  • 希尔排序时间复杂度不好计算,因为 gap 的取值很多,导致很难去计算,因此很多书中给出的希尔排序的时间复杂度都不固定。《数据结构(C语⾔版)》--- 严蔚敏书中给出的时间复杂度为:

2.3直接选择排序

  1. 在元素集合 array[i]--array[n-1] 中选择关键码最⼤(⼩)的数据元素

  2. 若它不是这组元素中的最后⼀个(第⼀个)元素,则将它与这组元素中的最后⼀个(第⼀个)元素交换

  3. 在剩余的 array[i]--array[n-2](array[i+1]--array[n-1]) 集合中,重复上述步骤,直到集合剩余 1 个元素

    void SlelectSort(int* arr, int n)
    {
    int begin = 0;
    int end = n - 1;
    while (begin < end)
    {
    int min = begin, max = begin;
    for (int i = begin + 1; i <= end; i++)
    {
    if (arr[i] < min)
    {
    min = i;
    }
    if (arr[i] > max)
    {
    max = i;
    }
    }

    复制代码
     	if (max = begin)
     	{
     		max = min;
     	}
     	Swap(&arr[min], &arr[begin]);
     	Swap(&arr[max], &arr[end]);
    
     	begin++;
     	end--;
     }

    }

直接选择排序的特性总结:

  1. 直接选择排序思考⾮常好理解,但是效率不是很好。实际中很少使⽤
  2. 时间复杂度: O(N2 )
  3. 空间复杂度: O(1)

未完待续~~~

相关推荐
励志要当大牛的小白菜2 小时前
ART配对软件使用
开发语言·c++·qt·算法
qq_513970442 小时前
力扣 hot100 Day56
算法·leetcode
PAK向日葵3 小时前
【算法导论】如何攻克一道Hard难度的LeetCode题?以「寻找两个正序数组的中位数」为例
c++·算法·面试
爱装代码的小瓶子4 小时前
数据结构之队列(C语言)
c语言·开发语言·数据结构
爱喝矿泉水的猛男5 小时前
非定长滑动窗口(持续更新)
算法·leetcode·职场和发展
YuTaoShao5 小时前
【LeetCode 热题 100】131. 分割回文串——回溯
java·算法·leetcode·深度优先
YouQian7726 小时前
Traffic Lights set的使用
算法
快乐飒男6 小时前
哈希表(c语言)
c语言·哈希算法·散列表
go54631584657 小时前
基于深度学习的食管癌右喉返神经旁淋巴结预测系统研究
图像处理·人工智能·深度学习·神经网络·算法
aramae7 小时前
大话数据结构之<队列>
c语言·开发语言·数据结构·算法