查找排序
顺序查找也称线性查找,它对顺序表和链表都是适用的。对于顺序表,可通过数组下标递增来顺序扫描每个元素;对于链表,可通过指针next来依次扫描每个元素 \begin{aligned} &\text{顺序查找也称线性查找,它对顺序表和链表都是适用的。对于顺序表,}\\&可通过数组下标递增来顺序扫描每个元素;对于链表,可通过指针 next 来依次扫描每个元素 \end{aligned} 顺序查找也称线性查找,它对顺序表和链表都是适用的。对于顺序表,可通过数组下标递增来顺序扫描每个元素;对于链表,可通过指针next来依次扫描每个元素
平衡二叉树: 保证任意节点的左右子树高度差不超过 1 \begin{aligned} &\color{red}\textbf{平衡二叉树}: \ \text{保证任意节点的左右子树高度差不超过 1} \end{aligned} 平衡二叉树: 保证任意节点的左右子树高度差不超过 1
概念:∙ 随机访问: 直接访问数据结构中的任意位置, 不需要按照顺序逐个访问。∙ 顺序访问: 按照特定的顺序依次访问, 时间与位置有关。折半查找的需要: 快速找到中位数、快速去掉一半元素因此使用折半查找的前提:1. 有序;2. 支持高效的随机访问, O(1) 时间内读 \begin{aligned} &\textbf{概念:} \\ &\quad \bullet \ \text{随机访问: 直接访问数据结构中的任意位置, 不需要按照顺序逐个访问。} \\ &\quad \bullet \ \text{顺序访问: 按照特定的顺序依次访问, 时间与位置有关。} \\ \\ &\text{折半查找的需要: 快速找到中位数、快速去掉一半元素} \\ &\color{orange}\text{因此使用折半查找的前提:} \\ &\color{orange}\quad 1. \ \text{有序;} \\ &\color{orange}\quad 2. \ \text{支持高效的随机访问, } O(1) \text{ 时间内读} \end{aligned} 概念:∙ 随机访问: 直接访问数据结构中的任意位置, 不需要按照顺序逐个访问。∙ 顺序访问: 按照特定的顺序依次访问, 时间与位置有关。折半查找的需要: 快速找到中位数、快速去掉一半元素因此使用折半查找的前提:1. 有序;2. 支持高效的随机访问, O(1) 时间内读
链表顺序表静态链表插入/删除O(1)O(n)O(1)读/写第 x个元素O(n)O(1)O(n) \begin{array}{c|c|c|c} \hline & \text{链表} & \text{顺序表} & \text{静态链表} \\ \hline \text{插入/删除} & O(1) & O(n) & O(1) \\ \hline \text{读/写第} \ x \text{个元素} & O(n) & O(1) & O(n) \\ \hline \end{array} 插入/删除读/写第 x个元素链表O(1)O(n)顺序表O(n)O(1)静态链表O(1)O(n)
5个结点的二叉树总共有多少种不同的形状卡特兰数(1n+1C2nn){1. n个元素入栈,有多少种不同的出栈序列2. n个结点的二叉树总共有多少种不同的形态 \begin{aligned} &\text{5个结点的二叉树总共有多少种不同的形状} \\ \\ &\color{blue}\text{卡特兰数}\left( \frac{1}{n+1}C_{2n}^{n}\right) \begin{cases} \color{red}\text{1. } n\text{个元素入栈,有多少种不同的出栈序列} \\ \color{red}\text{2. } n\text{个结点的二叉树总共有多少种不同的形态} \end{cases} \end{aligned} 5个结点的二叉树总共有多少种不同的形状卡特兰数(n+11C2nn){1. n个元素入栈,有多少种不同的出栈序列2. n个结点的二叉树总共有多少种不同的形态
nh=nh−2+nh−1+1nh:高度为h的平衡二叉树最少含有的结点数 \begin{aligned} &\color{red} n_h = n_{h-2} + n_{h-1} + 1 \\ \\ &\color{red} n_h: \text{高度为}h\text{的平衡二叉树最少含有的结点数} \end{aligned} nh=nh−2+nh−1+1nh:高度为h的平衡二叉树最少含有的结点数
将一个有序的关键字序列插入到一个初始为空的平衡二叉树中,若关键字个数 n=2h−1则这一颗AVL树一定是一颗满二叉树 \begin{aligned} &\text{将一个有序的关键字序列插入到一个初始为空的平衡二叉树中,若关键字个数 } n = 2^h - 1 \\ &\text{则这一颗AVL树一定是一颗满二叉树} \end{aligned} 将一个有序的关键字序列插入到一个初始为空的平衡二叉树中,若关键字个数 n=2h−1则这一颗AVL树一定是一颗满二叉树
平衡二叉树与红黑树比较{① 它们都是特殊的二叉排序树,是自平衡的,即在插入和删除节点时会自动调整树的结构,无需手动干预② 它们的树高都是O(logn)级别,树的高度可以视为最坏情况下查找所需时间的近似③ 平衡二叉树AVL对平衡的要求最高,即平衡因子只能为−1、0、1。平衡二叉树的树高一般比红黑树低,但插入和删除旋转调整的次数更多④ 虽然红黑树和平衡二叉树的树高的都是O(logn)的量级,但是平衡二叉树的高度一般是小于红黑树的树高的,因此查找速度快于红黑树结论2:有n个内部结点的红黑树的高度h≤2log2(n+1)。证明:由结论1可知,从根到叶结点(不含叶结点)的任何一条简单路径上都至少有一半是黑结点,因此,根的黑高至少为h/2,于是有n≥2h/2−1,即可求得结论。结论1:从根结点到叶结点的最长路径不大于最短路径的2倍 \begin{aligned} &\textbf{平衡二叉树与红黑树比较} \begin{cases} ① \ \text{它们都是特殊的二叉排序树,是自平衡的,即在插入和删除节点时会自动调整树的结构,无需手动干预} \\ ② \ \text{它们的树高都是} O(\text{log}n) \text{级别,树的高度可以视为最坏情况下查找所需时间的近似} \\ ③ \ \text{平衡二叉树AVL对平衡的要求最高,即平衡因子只能为}-1、0、1 \text{。平衡二叉树的树高一般比红黑树低,但插入和删除旋转调整的次数更多} \\ ④ \ \text{虽然红黑树和平衡二叉树的树高的都是} O(\text{log}n) \text{的量级,但是平衡二叉树的高度一般是小于红黑树的树高的,因此查找速度快于红黑树} \end{cases} \\ \\ &\text{结论2:有} n \text{个内部结点的红黑树的高度} h \leq 2\log_2(n + 1) \text{。} \\ &\text{证明:由结论1可知,从根到叶结点(不含叶结点)的任何一条简单路径上都至少有一半是黑结点,因此,根的黑高至少为} h/2 \text{,于是有} n \geq 2^{h/2} - 1 \text{,即可求得结论。} \\ \\ &\color{red}\textbf{结论1:从根结点到叶结点的最长路径不大于最短路径的2倍} \end{aligned} 平衡二叉树与红黑树比较⎩⎨⎧① 它们都是特殊的二叉排序树,是自平衡的,即在插入和删除节点时会自动调整树的结构,无需手动干预② 它们的树高都是O(logn)级别,树的高度可以视为最坏情况下查找所需时间的近似③ 平衡二叉树AVL对平衡的要求最高,即平衡因子只能为−1、0、1。平衡二叉树的树高一般比红黑树低,但插入和删除旋转调整的次数更多④ 虽然红黑树和平衡二叉树的树高的都是O(logn)的量级,但是平衡二叉树的高度一般是小于红黑树的树高的,因此查找速度快于红黑树结论2:有n个内部结点的红黑树的高度h≤2log2(n+1)。证明:由结论1可知,从根到叶结点(不含叶结点)的任何一条简单路径上都至少有一半是黑结点,因此,根的黑高至少为h/2,于是有n≥2h/2−1,即可求得结论。结论1:从根结点到叶结点的最长路径不大于最短路径的2倍
左根右根叶黑不红红黑路同 \begin{aligned} &\color{red}\text{左根右} \quad \color{red}\text{根叶黑} \\ &\color{red}\text{不红红} \quad \color{red}\text{黑路同} \end{aligned} 左根右根叶黑不红红黑路同
B树的定义和特点一棵m阶B树或为空树,或为满足如下特性的m叉树:1) 树中每个结点至多有m棵子树,即至多有m−1个关键字。2) 若根结点不是叶结点,则至少有2棵子树,即至少有1个关键字。3) 除根结点外的所有非叶结点至少有⌈m/2⌉棵子树,即至少有⌈m/2⌉−1个关键字。4) 所有非叶结点的结构如下:nP0K1P1K2P2⋯KnPn其中,Ki (i=1,2,⋯ ,n)为结点的关键字,且满足K1<K2<⋯<Kn;Pi (i=0,1,⋯ ,n)为指向子树根结点的指针,且指针Pi−1所指子树中所有结点的关键字均小于Ki,Pi所指子树中所有结点的关键字均大于Ki;n (⌈m/2⌉−1≤n≤m−1)为结点中关键字的个数。5) 所有的叶结点都出现在同一层次上,并且不带信息(可以视为外部结点或类似于折半查找判定树的失败结点,实际上这些结点并不存在,指向这些结点的指针为空) \begin{aligned} &\textbf{B树的定义和特点} \\ &\text{一棵} m \text{阶B树或为空树,或为满足如下特性的} m \text{叉树:} \\ &1) \ \text{树中每个结点至多有} m \text{棵子树,即至多有} m-1 \text{个关键字。} \\ &2) \ \text{若根结点不是叶结点,则至少有2棵子树,即至少有1个关键字。} \\ &3) \ \text{除根结点外的所有非叶结点至少有} \lceil m/2 \rceil \text{棵子树,即至少有} \lceil m/2 \rceil - 1 \text{个关键字。} \\ &4) \ \text{所有非叶结点的结构如下:} \\ &\quad \begin{array}{|c|c|c|c|c|c|c|c|c|} \hline n & P_0 & K_1 & P_1 & K_2 & P_2 & \cdots & K_n & P_n \\ \hline \end{array} \\ &\quad \text{其中,} K_i \ (i=1,2,\cdots,n) \text{为结点的关键字,且满足} K_1 < K_2 < \cdots < K_n; \\ &\quad P_i \ (i=0,1,\cdots,n) \text{为指向子树根结点的指针,且指针} P_{i-1} \text{所指子树中所有结点的关键字均小于} K_i, \\ &\quad P_i \text{所指子树中所有结点的关键字均大于} K_i; \\ &\quad n \ (\lceil m/2 \rceil - 1 \leq n \leq m-1) \text{为结点中关键字的个数。} \\ &5) \ \text{所有的叶结点}\text{都出现在同一层次上,并且不带信息(可以视为外部结点或类似于折半查找判定树的失败结点,}\\&实际上这些结点并不存在,指向这些结点的指针为空) \end{aligned} B树的定义和特点一棵m阶B树或为空树,或为满足如下特性的m叉树:1) 树中每个结点至多有m棵子树,即至多有m−1个关键字。2) 若根结点不是叶结点,则至少有2棵子树,即至少有1个关键字。3) 除根结点外的所有非叶结点至少有⌈m/2⌉棵子树,即至少有⌈m/2⌉−1个关键字。4) 所有非叶结点的结构如下:nP0K1P1K2P2⋯KnPn其中,Ki (i=1,2,⋯,n)为结点的关键字,且满足K1<K2<⋯<Kn;Pi (i=0,1,⋯,n)为指向子树根结点的指针,且指针Pi−1所指子树中所有结点的关键字均小于Ki,Pi所指子树中所有结点的关键字均大于Ki;n (⌈m/2⌉−1≤n≤m−1)为结点中关键字的个数。5) 所有的叶结点都出现在同一层次上,并且不带信息(可以视为外部结点或类似于折半查找判定树的失败结点,实际上这些结点并不存在,指向这些结点的指针为空)
最大高度→每个结点关键字个数最少最小高度→每个结点关键字个数最多B树的高度默认情况下不含叶结点这一层根 [1,m−1]=[1,4]非根 [⌈m2⌉−1,m−1]=[2,4] \begin{aligned} &\text{最大高度} \rightarrow \text{每个结点关键字个数最少} \\ &\text{最小高度} \rightarrow \text{每个结点关键字个数最多} \\ \\ &\color{blue}\text{B树的高度默认情况下不含叶结点这一层} \\ \\ &\color{red}\text{根} \ \ [1, m-1] = [1,4] \\ &\color{red}\text{非根} \ \ \left[ \lceil \frac{m}{2} \rceil - 1, m-1 \right] = [2,4] \end{aligned} 最大高度→每个结点关键字个数最少最小高度→每个结点关键字个数最多B树的高度默认情况下不含叶结点这一层根 [1,m−1]=[1,4]非根 [⌈2m⌉−1,m−1]=[2,4]
m阶B+树与m阶B树的主要差异如下:1) 在B+树中,具有n个关键字的结点只含有n棵子树,即每个关键字对应一棵子树;而在B树中,具有n个关键字的结点含有n+1棵子树。2) 在B+树中,每个结点(非根内部结点)的关键字个数n的范围是⌈m/2⌉≤n≤m (非叶根结点:2≤n≤m);而在B树中,每个结点(非根内部结点)的关键字个数n的范围是⌈m/2⌉−1≤n≤m−1 (根结点:1≤n≤m−1)。3) 在B+树中,叶结点包含了全部关键字,非叶结点中出现的关键字也会出现在叶结点中;而在B树中,最外层的终端结点包含的关键字和其他结点包含的关键字是不重复的。 \begin{aligned} &\boldsymbol{m} \text{阶B+树与} \boldsymbol{m} \text{阶B树的主要差异如下:} \\ &1) \ \text{在B+树中,具有} n \text{个关键字的结点只含有} n \text{棵子树,} \\&即每个关键字对应一棵子树;而在B树中,具有n \text{个关键字的结点含有} n+1 \text{棵子树。} \\ &2) \ \text{在B+树中,每个结点}(非根内部结点)的关键字个数 n \text{的范围是} \lceil m/2 \rceil \leq n \leq m \ \\&(\text{非叶根结点:} 2 \leq n \leq m);\text{而在B树中,每个结点}\\&(非根内部结点)的关键字个数 n \text{的范围是} \lceil m/2 \rceil - 1 \leq n \leq m-1 \ (\text{根结点:} 1 \leq n \leq m-1)。 \\ &3) \ \text{在B+树中,叶结点包含了全部关键字,非叶结点中出现的关键字也会出现在叶结点中;}\\& 而在B树中,最外层的终端结点包含的关键字和其他结点包含的关键字是不重复的。\end{aligned} m阶B+树与m阶B树的主要差异如下:1) 在B+树中,具有n个关键字的结点只含有n棵子树,即每个关键字对应一棵子树;而在B树中,具有n个关键字的结点含有n+1棵子树。2) 在B+树中,每个结点(非根内部结点)的关键字个数n的范围是⌈m/2⌉≤n≤m (非叶根结点:2≤n≤m);而在B树中,每个结点(非根内部结点)的关键字个数n的范围是⌈m/2⌉−1≤n≤m−1 (根结点:1≤n≤m−1)。3) 在B+树中,叶结点包含了全部关键字,非叶结点中出现的关键字也会出现在叶结点中;而在B树中,最外层的终端结点包含的关键字和其他结点包含的关键字是不重复的。
4) 在B+树中,叶结点包含信息,所有非叶结点仅起索引作用,非叶结点的每个索引项只含有对应子树的最大关键字和指向该子树的指针,不含有对应记录的存储地址。这样能使一个磁盘块存储更多的关键字,使得磁盘读/写次数更少,查找速度更快。5) 在B+树中,用一个指针指向关键字最小的叶结点,将所有叶结点串成一个线性链表。 \begin{aligned} &4) \ \text{在B+树中,叶结点包含信息,所有非叶结点仅起索引作用,非叶结点的每个索引项}\\&只含有对应子树的最大关键字和指向该子树的指针,不含有对应记录的存储地址。\\&这样能使一个磁盘块存储更多的关键字,使得磁盘读/写次数更少,查找速度更快。 \\ &5) \ \text{在B+树中,用一个指针指向关键字最小的叶结点,将所有叶结点串成一个线性链表。} \end{aligned} 4) 在B+树中,叶结点包含信息,所有非叶结点仅起索引作用,非叶结点的每个索引项只含有对应子树的最大关键字和指向该子树的指针,不含有对应记录的存储地址。这样能使一个磁盘块存储更多的关键字,使得磁盘读/写次数更少,查找速度更快。5) 在B+树中,用一个指针指向关键字最小的叶结点,将所有叶结点串成一个线性链表。
散列表(也称哈希表):根据关键字而直接进行访问的数据结构。也就是说,散列表建立了关键字和存储地址之间的一种直接映射关系。 \begin{aligned} &\text{散列表(也称哈希表):根据关键字而直接进行访问的数据结构。也就是说,散列表建立了} \\ &\text{关键字和存储地址之间的一种直接}\text{映射}\text{关系。} \end{aligned} 散列表(也称哈希表):根据关键字而直接进行访问的数据结构。也就是说,散列表建立了关键字和存储地址之间的一种直接映射关系。
2) 散列表的查找效率取决于三个因素:散列函数、处理冲突的方法和装填因子。装填因子。散列表的装填因子一般记为α,定义为一个表的装满程度,即α=表中记录数n散列表长度m散列函数可能会把两个或两个以上的不同关键字映射到同一地址,称这种情况为冲突2) 散列表的查找效率取决于三个因素:散列函数、处理冲突的方法和装填因子。 \begin{aligned} &2) \ \text{散列表的查找效率取决于三个因素:散列函数、处理冲突的方法和装填因子。} \\ &\text{装填因子。散列表的装填因子一般记为} \alpha, \text{定义为一个表的装满程度,即} \\ &\quad \alpha = \frac{\text{表中记录数}n}{\text{散列表长度}m} \\ \\ &\text{散列函数可能会把两个或两个以上的不同关键字映射到同一地址,称这种情况为冲突} \\ \\ &2) \ \text{散列表的查找效率取决于三个因素:散列函数、处理冲突的方法和装填因子。} \end{aligned} 2) 散列表的查找效率取决于三个因素:散列函数、处理冲突的方法和装填因子。装填因子。散列表的装填因子一般记为α,定义为一个表的装满程度,即α=散列表长度m表中记录数n散列函数可能会把两个或两个以上的不同关键字映射到同一地址,称这种情况为冲突2) 散列表的查找效率取决于三个因素:散列函数、处理冲突的方法和装填因子。
1) 线性探测法,也称线性探测再散列法。di=1,2,⋯ ,m−1。它的特点是:冲突发生时,顺序查看表中下一单元(探测到表尾地址m−1时,下一个探测地址是表首地址0),直到找出一个空闲单元(当表未填满时一定能找到一个空闲单元)或查遍全表。线性探测法可能使第i个散列地址的同义词存入第i+1个散列地址,这样本应存入第i+1个散列地址的元素就争夺第i+2个散列地址的元素的地址……从而造成大量元素在相邻的散列地址上聚集(或堆积)起来,大大降低了查找效率。2) 平方探测法,也称二次探测法。di=12,−12,22,−22,⋯ ,k2,−k2,其中k≤m/2,散列表长度m必须是一个可以表示成4k+3的素数。平方探测法是一种处理冲突的较好方法,可以避免出现“堆积”问题,它的缺点是不能探测到散列表上的所有单元,但至少能探测到一半单元。3) 双散列法。di=i×Hash2(key)。需要使用两个散列函数,当通过第一个散列函数H(key)得到的地址发生冲突时,则利用第二个散列函数Hash2(key)计算该关键字的地址增量。它的具体散列函数形式如下:Hi=(H(key)+i×Hash2(key))%m初始探测位置H0=H(key)%m。i是冲突的次数,初始为0。4) 伪随机序列法。di=伪随机序列。 \begin{aligned} &1) \ \text{线性探测法,也称线性探测再散列法。} d_i=1,2,\cdots,m-1 \text{。它的特点是:} \\&冲突发生时,顺序查看表中下一单元(探测到表尾地址m-1 \text{时,下一个探测地址是表首地址0),} \\&直到找出一个空闲单元(当表未填满时一定能找到一个空闲单元)或查遍全表。\\ &\quad \text{线性探测法可能使第} i \text{个散列地址的同义词存入第}\\& i+1 \text{个散列地址,这样本应存入第} i+1 \text{个散列地址的元素就争夺第} i+2 \text{个散列地址的元素的地址……} \\&从而造成大量元素在相邻的散列地址上聚集(或堆积)起来,大大降低了查找效率。\\ \\ &2) \ \text{平方探测法,也称二次探测法。} d_i=1^2,-1^2,2^2,-2^2,\cdots,k^2,-k^2 \text{,其中} k \leq m/2 \\&\text{,散列表长度} m \text{必须是一个可以表示成} 4k+3 \text{的素数。} \\ &\quad \text{平方探测法是一种处理冲突的较好方法,可以避免出现“堆积”问题,} \\&它的缺点是不能探测到散列表上的所有单元,但至少能探测到一半单元。\\ \\ &3) \ \text{双散列法。} d_i=i \times \text{Hash}_2(\text{key}) \text{。需要使用两个散列函数,当通过第一个散列函数} H(\text{key})\\& \text{得到的地址发生冲突时,则利用第二个散列函数} \text{Hash}_2(\text{key}) \text{计算该关键字的地址增量。它的具体散列函数形式如下:} \\ &\quad \quad H_i=(H(\text{key}) + i \times \text{Hash}_2(\text{key})) \% m \\ &\quad \text{初始探测位置} H_0=H(\text{key}) \% m \text{。} i \text{是冲突的次数,初始为0。} \\ \\ &4) \ \text{伪随机序列法。} d_i=\text{伪随机序列。} \end{aligned} 1) 线性探测法,也称线性探测再散列法。di=1,2,⋯,m−1。它的特点是:冲突发生时,顺序查看表中下一单元(探测到表尾地址m−1时,下一个探测地址是表首地址0),直到找出一个空闲单元(当表未填满时一定能找到一个空闲单元)或查遍全表。线性探测法可能使第i个散列地址的同义词存入第i+1个散列地址,这样本应存入第i+1个散列地址的元素就争夺第i+2个散列地址的元素的地址……从而造成大量元素在相邻的散列地址上聚集(或堆积)起来,大大降低了查找效率。2) 平方探测法,也称二次探测法。di=12,−12,22,−22,⋯,k2,−k2,其中k≤m/2,散列表长度m必须是一个可以表示成4k+3的素数。平方探测法是一种处理冲突的较好方法,可以避免出现“堆积”问题,它的缺点是不能探测到散列表上的所有单元,但至少能探测到一半单元。3) 双散列法。di=i×Hash2(key)。需要使用两个散列函数,当通过第一个散列函数H(key)得到的地址发生冲突时,则利用第二个散列函数Hash2(key)计算该关键字的地址增量。它的具体散列函数形式如下:Hi=(H(key)+i×Hash2(key))%m初始探测位置H0=H(key)%m。i是冲突的次数,初始为0。4) 伪随机序列法。di=伪随机序列。
存储效率 (空间利用率)=元素占有的空间整个散列表占据的空间 \begin{aligned} &\text{存储效率} \ (\text{空间利用率}) = \frac{\text{元素占有的空间}}{\text{整个散列表占据的空间}} \end{aligned} 存储效率 (空间利用率)=整个散列表占据的空间元素占有的空间
装的元素越多(填装因子越多),平均查找长度一般会增加散列函数、冲突解决策略安排得越好,越合理,平均查找长度越少 \begin{aligned} &\text{装的元素越多(}\text{填装因子}\text{越多),平均查找长度一般会增加} \\ &\text{散列函数、冲突解决策略}\text{安排得越好,越合理,平均查找长度越少} \end{aligned} 装的元素越多(填装因子越多),平均查找长度一般会增加散列函数、冲突解决策略安排得越好,越合理,平均查找长度越少
散列表平均查找次数的计算:假设H(key)=key%m、表长度为n、已存关键字数为k。① 计算ASL成功时考虑散列表中存储的每个关键字,将查找到每个关键字需要的次数求和,再除以k;② 计算ASL失败时考虑映射到数组的所有可能位置即%m=0,1,2,…,m−1共m种情况,把每种失败情况的查找次数求和,再除以m。 \begin{aligned} &\text{散列表平均查找次数的计算:假设} H(\text{key})=\text{key}\%m \text{、表长度为} n \text{、已存关键字数为} k \text{。} \\ &① \ \text{计算} \text{ASL}_{\text{成功}} \text{时考虑散列表中存储的每个关键字,将查找到每个关键字需要的次数求和,再除以} k; \\ &② \ \text{计算} \text{ASL}_{\text{失败}} \text{时考虑映射到数组的所有可能位置即} \%m=0,1,2,\dots,m-1 \text{共} m \text{种情况,把每种失败情况的查找次数求和,再除以} m \text{。} \end{aligned} 散列表平均查找次数的计算:假设H(key)=key%m、表长度为n、已存关键字数为k。① 计算ASL成功时考虑散列表中存储的每个关键字,将查找到每个关键字需要的次数求和,再除以k;② 计算ASL失败时考虑映射到数组的所有可能位置即%m=0,1,2,…,m−1共m种情况,把每种失败情况的查找次数求和,再除以m。
直接插入排序{最好情况→元素基本有序最坏情况→元素逆序 \begin{aligned} &\color{red}\text{直接插入排序} \begin{cases} \color{red}\text{最好情况} \rightarrow \color{blue}\text{元素基本有序} \\ \color{red}\text{最坏情况} \rightarrow \color{blue}\text{元素逆序} \end{cases} \end{aligned} 直接插入排序{最好情况→元素基本有序最坏情况→元素逆序
![![[Pasted image 20251215181648.png]]](https://i-blog.csdnimg.cn/direct/7980c6d280e54d84a49bc67225545349.png)
![![[Pasted image 20251215181711.png]]](https://i-blog.csdnimg.cn/direct/2d46a12e2e7e4843b49d60729842142f.png)
![![[Pasted image 20251215181915.png]]](https://i-blog.csdnimg.cn/direct/a16b088950ce43cd944c7cb6957721f0.png)
前面介绍过的排序算法都是在内存中进行的(称为内部排序)。而在许多应用中,经常需要对大文件进行排序,因为文件中的记录很多,无法将整个文件复制进内存中进行排序。因此,需要将待排序的记录存储在外存上,排序时再把数据一部分一部分地调入内存进行排序,在排序过程中需要多次进行内存和外存之间的交换。这种排序算法就称为外部排序。 \begin{aligned} &\text{前面介绍过的排序算法都是在内存中进行的(称为内部排序)。而在许多应用中,}\\&经常需要对大文件进行排序,因为文件中的记录很多,无法将整个文件复制进内存中进行排序。\\&因此,需要将待排序的记录存储在外存上,排序时再把数据一部分一部分地调入内存进行排序, \\ &\text{在排序过程中需要多次进行内存和外存之间的交换。这种排序算法就称为外部排序。} \end{aligned} 前面介绍过的排序算法都是在内存中进行的(称为内部排序)。而在许多应用中,经常需要对大文件进行排序,因为文件中的记录很多,无法将整个文件复制进内存中进行排序。因此,需要将待排序的记录存储在外存上,排序时再把数据一部分一部分地调入内存进行排序,在排序过程中需要多次进行内存和外存之间的交换。这种排序算法就称为外部排序。
外部排序{① 从外存读入数据进行内部排序得到有序初始归并段优化思路:减少有序初始归并段数量→置换选择排序② 对这些归并段进行逐趟归并优化思路:增大归并趟数而不影响内部归并的比较次数 \begin{aligned} &\text{外部排序} \begin{cases} ① \ \text{从外存读入数据进行内部排序得到有序初始归并段} \\ \quad \text{优化思路:减少有序初始归并段数量} \rightarrow{} \text{置换选择排序} \\ \\ ② \ \text{对这些归并段进行逐趟归并}\\ \quad \text{优化思路:增大归并趟数而不影响内部归并的比较次数} \end{cases} \end{aligned} 外部排序⎩⎨⎧① 从外存读入数据进行内部排序得到有序初始归并段优化思路:减少有序初始归并段数量→置换选择排序② 对这些归并段进行逐趟归并优化思路:增大归并趟数而不影响内部归并的比较次数
![[[Pasted image 20251215182354.png]]](https://i-blog.csdnimg.cn/direct/7038da2cab844ab0a409c8b4ee93335d.png)
![![[Pasted image 20251215182457.png]]](https://i-blog.csdnimg.cn/direct/a1fa4975b8c64f53876132db644dfd21.png)
归并多个升(降)序序列:1. 设置多个指针指向每个序列的第一个元素。2. 重复如下步骤直到只剩一个序列未处理完: 将其中较小(或较大)的一方加入到结果序列中,并将对应的指针向后移动一位。3. 将原序列中还未处理完序列的所有元素依次加入结果序列。归并前的序列和归并后的序列升降是相同的。外部排序:∙ 败者树中每个非终端节点表示其左、右孩子节点中的“败者”。∙ 通过冠军选出的关键字在结果序列前面,因此:∙ 如果结果是升序,则冠军选出的是当前最小关键字∙ 如果结果是降序,则冠军选出的是当前最大关键字 \begin{aligned} &\text{归并多个升(降)序序列:} \\ &1. \ \text{设置多个指针指向每个序列的第一个元素。} \\ &2. \ \text{重复如下步骤直到只剩一个序列未处理完: 将其中较小(或较大)的一方加入到结果序列中,并将对应的指针向后移动一位。} \\ &3. \ \text{将原序列中还未处理完序列的所有元素依次加入结果序列。} \\ &\color{orange}\text{归并前的序列和归并后的序列升降是相同的。} \\ \\ &\text{外部排序:} \\ &\bullet \ \text{败者树中每个非终端节点表示其左、右孩子节点中的“败者”。} \\ &\bullet \ \text{通过冠军选出的关键字在结果序列前面,因此:} \\ &\quad \bullet \ \text{如果结果是升序,则冠军选出的是当前最小关键字} \\ &\quad \bullet \ \text{如果结果是降序,则冠军选出的是当前最大关键字} \end{aligned} 归并多个升(降)序序列:1. 设置多个指针指向每个序列的第一个元素。2. 重复如下步骤直到只剩一个序列未处理完: 将其中较小(或较大)的一方加入到结果序列中,并将对应的指针向后移动一位。3. 将原序列中还未处理完序列的所有元素依次加入结果序列。归并前的序列和归并后的序列升降是相同的。外部排序:∙ 败者树中每个非终端节点表示其左、右孩子节点中的“败者”。∙ 通过冠军选出的关键字在结果序列前面,因此:∙ 如果结果是升序,则冠军选出的是当前最小关键字∙ 如果结果是降序,则冠军选出的是当前最大关键字
5万+

被折叠的 条评论
为什么被折叠?



