数据结构—动画表示八大排序算法

Posted 一口Linux

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构—动画表示八大排序算法相关的知识,希望对你有一定的参考价值。


一、直接插入排序

数据结构—动画表示八大排序算法_数据结构

基本思想:

我们平时玩扑克牌时,摸牌阶段的排序就用到了插入排序的思想

  • 1、当插入第n个元素时,前面的n-1个数已经有序
  • 2、用这第n个数与前面的n-1个数比较,找到要插入的位置,将其插入(原来位置上的数不会被覆盖,因为提前保存了)
  • 3、原来位置上的数据,依次后移

具体实现:

  • ①单趟的实现(将x插入到 [0,end] 的有序区间)

即一般情况下的插入,我们随机列举了一些数字,待插入的数字分为两种情况


(1)待插入的数字是在前面有序数字的中间数,直接比较将x赋值给end+1位置
(2)x是最小的一个数,end就会到达-1的位置,最后直接将x赋值给end+1位置
数据结构—动画表示八大排序算法_数据结构_02


  • ②整个数组排序的实现

我们一开始并不知道数组是不是有序的,所以我们控制下标,end从0开始,将end+1位置的值始终保存到x中,循环进行单趟排序即可,最后结束时end=n-2,n-1位置的数字保存到x中

数据结构—动画表示八大排序算法_动画_03

总体代码:

void InsertSort(int* a, int n)

assert(a);

for (int i = 0; i < n - 1; ++i)

int end = i;
int x=a[end+1];//将end后面的值保存到x里面了
//将x插入到[0,end]的有序区间
while (end >= 0)

if (a[end] > x)

a[end + 1] = a[end]; //往后挪动一位
--end;

else

break;


a[end + 1] = x; //x放的位置都是end的后一个位置

直接插入排序总结:

  • ①元素越接近有序,直接插入排序的效率越高
  • ②时间复杂度:O(N^2)

最坏的情况下,每次插入一个数字,前面的数字都要挪动一下,一共需要挪动1+2+3+……+n=n(n+1)/2

③空间复杂度:O(1)

没有借助额外的空间,只用到常数个变量

二、希尔排序

数据结构—动画表示八大排序算法_动画_04

基本思想:

  • 1、先选定个小于n的数字作为gap,所有距离为gap的数分为一组进行预排序(直接插入排序)
  • 2、再选一个小于gap的数,重复①的操作
  • 3、当gap=1时,相当于整个数组就是一组,再进行一次插入排序即可整体有序

例如:

数据结构—动画表示八大排序算法_数据结构_05

具体实现:

①单组排序

和前面的直接插入相同,就是把原来的间隔为1,现在变为gap了,每组分别进行预排序

数据结构—动画表示八大排序算法_数组_06

②多组进行排序

数据结构—动画表示八大排序算法_数据结构_07

③整个数组进行排序(控制gap)

多次预排序(gap>1)+ 一次插入排序(gap==1)

(1)gap越大,预排越快,越不接近于有序

(2)gap越小,预排越慢,越接近有序

结果就是:

数据结构—动画表示八大排序算法_数据结构_08

总体代码:

void ShellSort(int* a, int n)


int gap = n;
while (gap > 1)

gap /= 2;

for (int i = 0; i < n - gap; i++)

int end = i;
int x = a[end + gap];
while (end >= 0)

if (a[end] > x)

a[end + gap] = a[end];
end -= gap;

else

break;


a[end + gap] = x;


希尔排序总结:

  • ①希尔排序是对直接插入排序的优化
  • ②时间复杂度:O(N^1.3)
  • ③空间复杂度:O(1)

三、选择排序

数据结构—动画表示八大排序算法_递归_09

基本思想:

每次从数组中选出最大的或者最小的,存放在数组的最右边或者最左边,直到全部有序

具体实现:

我们这里进行了优化,一次排序中,直接同时选出最大的数(a[maxi])和最小的数(a[mini])放在最右边和最左边,这样排序效率是原来的2倍

  • ①单趟排序

找到最小的数字(a[mini])和最大的数字(a[maxi]),将他们放在最左边和最右边

ps:其中的begin,end保存记录左右的下标,mini,maxi记录保存最小值和最大值得下标

数据结构—动画表示八大排序算法_数组_10

  • ②整个数组排序

begin++和end–这样下次就可以排剩下的n-2个数字,再次进行单趟,如此可构成循环,直到begin小于end

整体代码:

void SelectSort(int* a, int n)

int begin = 0,end = n - 1;

while (begin<end)

int mini = begin, maxi = begin;

for (int i = begin; i <= end; i++)

if (a[i] < a[mini])

mini = i;

if (a[i] > a[maxi])

maxi = i;


Swap(&a[mini], &a[begin]);
//当begin==maxi时,最大值会被换走,修正一下
if (begin==maxi)

maxi=mini;

Swap(&a[maxi], &a[end]);
begin++;
end--;

直接选择排序总结:

  • ①直接选择排序很好理解,但实际效率不高,很少使用
  • ②时间复杂度:O(N^2)
  • ③空间复杂度:O(1)

四、堆排序

基本思想:

  • 1、将待排序的序列构造成一个大堆,根据大堆的性质,当前堆的根节点(堆顶)就是序列中最大的元素;
  • 2、将堆顶元素和最后一个元素交换,然后将剩下的节点重新构造成一个大堆;
  • 3、重复步骤2,如此反复,从第一次构建大堆开始,每一次构建,我们都能获得一个序列的最大值,然后把它放到大堆的尾部。最后,就得到一个有序的序列了。
  • 小结论:

    排升序,建大堆

    排降序,建小堆

具体实现:、

  • ①向下调整算法

我们将给定的数组序列,建成一个大堆,建堆从根节点开始就需要多次的向下调整算法


堆的向下调整算法(使用前提):
(1)若想将其调整为小堆,那么根结点的左右子树必须都为小堆。
(2)若想将其调整为大堆,那么根结点的左右子树必须都为大堆。


数据结构—动画表示八大排序算法_数据结构_11

向下调整算法的基本思想:

  • 1、从根节点开始,选出左右孩子值较大的一个
  • 2、如果选出的孩子的值大于父亲的值,那么就交换两者的值
  • 3、将大的孩子看做新的父亲,继续向下调整,直到调整到叶子节点为止
    数据结构—动画表示八大排序算法_数组_12
//向下调整算法
//以建大堆为例
void AdJustDown(int* a, int n, int parent)

int child = parent * 2 + 1;
//默认左孩子较大
while (child < n)

if (child + 1 < n && a[child+1] > a[child ])//如果这里右孩子存在,
//且更大,那么默认较大的孩子就改为右孩子

child++;

if(a[child]>a[parent])

Swap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;

else

break;


  • ②建堆(将给定的任意数组建成大堆)


建堆思想:
从倒数第一个非叶子节点开始,从后往前,依次将其作为父亲,依次向下调整,一直调整到根的位置


以上是关于数据结构—动画表示八大排序算法的主要内容,如果未能解决你的问题,请参考以下文章

C语言编程八大排序之堆排序

要想学好八大排序算法这篇文章你不得不看,巨详细王大爷表示都看得懂

八大排序算法之基数排序

八大排序算法及其比较

八大排序算法总结

数据结构常见的八大排序算法(详细整理)