二叉树余题,排序、直接插入排序、希尔排序

目录

一、余题

二、排序

1.概念

2.常见排序

3、插入排序

3.1、直接插入排序

3.2、希尔排序

一、余题

1.某完全⼆叉树按层次输出(同⼀层从左到右)的序列为 ABCDEFGH 。该完全⼆叉树的前序序列为(A)

A ABDHECFG

B ABCDEFGH

C HDBEAFCG

D HDEBFGCA

2.⼆叉树的先序遍历和中序遍历如下:先序遍历:EFHIGJK;中序遍历:HFIEJKG.则⼆叉树根结点为 (A)

A E

B F

C G

D H

3.设⼀课⼆叉树的中序遍历序列:badce,后序遍历序列:bdeca,则⼆叉树前序遍历序列为(D)。

A adbce

B decab

C debac

D abcde

4.某⼆叉树的后序遍历序列与中序遍历序列相同,均为 ABCDEF ,则按层次输出(同⼀层从左到右)的序列为(A)

A FEDCBA

B CBAFED

C DEFCBA

D ABCDEF

二、排序

1.概念

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

2.常见排序

排序分为:比较排序和非比较排序

以下为比较排序:

3、插入排序

直接插⼊排序是⼀种简单的插⼊排序法,其基本思想是:把待排序的记录按其关键码值的⼤⼩逐个插 ⼊到⼀个已经排好序的有序序列中,直到所有的记录插⼊完为⽌,得到⼀个新的有序序列 。

3.1、直接插入排序

当插⼊第 i(i>=1) 个元素时,前⾯的 array0 , array1 , ... , arrayi-1已经排好序,此时⽤ arrayi 的排序码与 arrayi-1 , arrayi-2 , ... 的排序码顺序进⾏⽐较,找到插⼊位置即将 arrayi 插⼊,原来位置上的元素顺序后移

复制代码
void InsertSort(int* a, int n)
{
 for (int i = 0; i < n-1; i++)
 {
  int end = i ;
  int tmp = a[end + 1];
  while (end >= 0)
  {
   if (a[end] > tmp)
   {
    a[end + 1] = a[end];
    end--;
   }
   else
   {
    break;
   }
  }
 a[end + 1] = tmp;
 }
}

元素集合越接近有序,直接插⼊排序算法的时间效率越⾼

时间复杂度:O(N^2) -->最差的情况(当数组数据大的在前面,数据小的都在后面)

O(N)-->最好的情况(当数组本身有序或数据小的在前,数据大的在后面)

空间复杂度:O(1)

3.2、希尔排序

希尔排序法⼜称缩⼩增量法。希尔排序法的基本思想是:先选定⼀个整数(通常是gap = n/3+1),把 待排序⽂件所有记录分成各组,所有的距离相等的记录分在同⼀组内,并对每⼀组内的记录进⾏排 序,然后gap=gap/3+1得到下⼀个整数,再将数组分成各组,进⾏插⼊排序,当gap=1时,就相当于 直接插⼊排序。

它是在直接插⼊排序算法的基础上进⾏改进⽽来的,综合来说它的效率肯定是要⾼于直接插⼊排序算 法的。

希尔排序是对直接插⼊排序的优化。

当 gap > 1 时都是预排序,⽬的是让数组更接近于有序。当 gap == 1 时,数组已经接近有序 的了,这样就会很快。这样整体⽽⾔,可以达到优化的效果。

存在大的数据在前,小的数据在后,但是每组比较的数据量要小

数据量大,但是比较次数少

小的数据在前面分组排序的过程中已经到前面去了,大的数据已经放到后面

gap > 1 , 预排序

gap == 1 , 直接插入排序

复制代码
void ShellSort(int * a,int n)
{
 int gap = n;
 while (gap > 1)
 {
  //推荐写法:除3
  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/2导致循环次数增多,+1是为了保证最后一次gap一定会变成1

希尔排序的时间复杂度计算 希尔排序的时间复杂度估算:

外层循环: 外层循环的时间复杂度可以直接给出为: O(log2 n) 或者 O(log3 n) ,即 O(log n)

内层循环:假设n=9,若gap为3,则一共gap组,每组n/gap个数据

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

总计最坏情况下移动总数为: gap ∗ 1 + 2 + 3 + .... + ( n / gap -1)

gap取值有(以除3为例):n/3 n/9 n/27 ...... 2 1

• 当gap为n/3时,移动总数为: n / 3 * (1 + 2) = n

• 当gap为n/9时,移动总数为: n / 9 * (1 + 2 + 3 + .... + 8) = n / 9 * 8(1 + 8) / 2 = 4n

• 最后⼀躺,gap=1即直接插⼊排序,内层循环排序消耗为n

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

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

最坏的时间复杂度为O(N ^ 2)---> 数组本身有序的情况并不多见

这相比冒泡排序的它只能是O(N ^ 2)

相关推荐
是main不是漫32 分钟前
【双指针|LeetCode1089 复写零】巧用逆向思路,破解原地覆盖陷阱
数据结构·算法·leetcode
是main不是漫35 分钟前
【C++——类和对象(上)】筑基篇:以封装奠定面向对象之基
c语言·开发语言·c++
apcipot_rain4 小时前
C++转Java日记(06)
java·开发语言
专注仿真10 小时前
知识问答模型用到的算法集详解及代码实例
python·算法·代码·大模型训练·控制算法
罗西的思考11 小时前
【轻量化复刻大模型 / KIMI K3】AttnRes 模块交互式演示
人工智能·算法·机器学习
SomeOtherTime11 小时前
Rust所有权(AI回答)
开发语言·后端·rust
Easyhood11 小时前
Android 开发入门实践(十四):Compose 副作用入门与四个常用 API
android·开发语言·kotlin·android jetpack·compose
白杨尚青12 小时前
C++进阶篇(六):map 和 set 的模拟实现——用红黑树封装 mymap/myset(迭代器 + operator[])
开发语言·c++·迭代器·stl·set·map·红黑树
好悬给我拽开线15 小时前
ZILOT 论文解析
算法