目录
一,查找的概念
二,线性查找
1,顺序查找
2,折半查找
3,分块查找
三,树表的查找
1,二叉排序树
(1)查找方式:
(2)、二叉排序树的插入和生成
(3)、二叉排序树的删除
2,平衡二叉树
(1)、什么是平衡二叉树
(2)、平衡二叉树的插入调整
(1)LL型调整
(2)RR型调整
(3)LR型调整
(4)RL型调整
3,B-树
4,B+树
四,哈希查找
1,基本概念
2,哈希函数构造方法
3 哈希冲突解决方法
1、开放定址法
2、拉链法
一,查找的概念
查找表:是由一组记录组成的表或文件,而每个记录由若干个 数据项组成,并假设每个记录都有一个能唯一标识该记录的关键字。 |
内查找:若整个查找过程都在内存进行,则称之为内查找; |
外查找:若查找过程中需要访问外存,则称之为外查找。 |
动态查找表;若在查找的同时对表做修改操作(如插入和删除), 则相应的表称之为动态查找表;否则称之为静态查找表。 |
平均查找长度(ASL): 其中:n是查找表中记录的个数。pi 是查找第i个记录的概率,ci 是找到第i个记录所需进行的比较次数。 |
二,线性查找
1,顺序查找
顺序表的表示:
typedef struct{KeyType key;...//其他数据
}ElemType;typedef struct{ElemType *R;int length;
}SSTable;
顺序查找的算法如下(在顺序表R[0..n-1]中查找关键字为k的元 素,成功时返回找到的元素的逻辑序号,失败时返回0)
int Search_Seq(SSTable ST ,KEYType key){for(i=ST.length;i>=1;--i)if(ST.R[i].key==key)return i;return 0;
}
增加"哨兵"和"监视哨",将key值放到数组下标为0的地方,这样就可以免去每次对i的比较验证,加快查找速度,这样查找可以使查找的时间减少一半
int Search_Seq(SSTable ST ,KEYType key){ST.R[0].key=key;for(i=ST.length;ST.R[i].key!=key;--i);return i;
}
成功情况下的平均查找长度ASL: (无论是否有序查找长度不变) |
不成功情况下的平均查找长度ASL: n (有序表和无序表的平均查找长度是不同的) |
2,折半查找
折半查找也称为二分查找,要求线性表中的记录必须己按关键 字值有序(递增或递减)排列。
int BinSearch(SeqList R,int n,KeyType k){ int low=1,high=ST.length,mid;while (low<=high){mid=(low+high)/2;if (ST.R[mid].key==k)return mid;if (k<ST.R[mid].key)high=mid-1;elselow=mid+1;}return 0;
}
二分查找过程可用二叉树来描述: 把当前查找区间的中间位置上的记录作为 根; 左子表和右子表中的记录分别作为根的 左子树和右子树。 这样的二叉树称为判定树或比较树
成功时的平均查找长度为: |
失败时的平均查找长度为:外部节点(i-n+1)*(所在层数-1)/外部节点总数 |
对于n个元素,二分查找,成功时最多的关键字比较次数为:log2(n+1) ; 不成功时关键字比较次数为:log2(n+1) 。 |
二分查找的时间复杂度为O(log2n)。 |
内部节点为n,则外部节点为n+1 |
3,分块查找
索引存储结构=数据表+ 索引表;
分块查找方法: 索引表(有序):可以顺序查找块,也可以二分查找块。
数据块(无序):只能 顺序查找块中元素。
查找效率:
顺序查找 | 折半查找 | 分块查找 | |
ASL | 最大 | 最小 | 中间 |
表结构 | 有序表/无序表 | 有序表 | 分块有序 |
存储结构 | 顺序表/线性链表 | 顺序表 | 顺序表/线性链表 |
三,树表的查找
1,二叉排序树
二叉排序树(简称BST)又称二叉查找(搜索)树. 其定义为:二叉 排序树或者是空树,或者是满足如下性质(BST性质)的二叉树: 若它的左子树非空,则左子树上所有节点值(指关键字值)均小于根节点值; 若它的右子树非空,则右子树上所有节点值均大于根节点值; 左、右子树本身又各是一棵二叉排序树
二叉排序树的中序遍历序列递增
typedef struct node{KeyType key;//关键字项InfoType data;//其他数据域struct node *lchild,*rchild; //左右孩子指针
} BSTNode;
(1)查找方式:
BSTNode *SearchBST(BSTNode *bt,KeyType k){if (bt==NULL|| bt->key==k) //递归出口return bt;if (k<bt->key)return SearchBST(bt->lchild,k); //在左子树中递归查找elsereturn SearchBST(bt->rchild,k); //在右子树中递归查找
}
n个节点的二叉排序树的平均查找长度和树的形态有关 |
最好情况:ASL:时间复杂度:O(log2 N) |
最坏情况:ASL: 时间复杂度:O(n) |
(2)、二叉排序树的插入和生成
(1)若二叉排序树T为空,则创建一个key域为k的节点,将它作为 根节点;
(2)否则将k和根节点的关键字比较,若两者相等,则说明树中已 有此关键字k,无须插入,直接返回0;
(3)若k<T->key,则将k插入根节点的左子树中。
(4)否则将它插入右子树中。
任何节点插入到二叉排序树时,都是以叶节点插入的。
(3)、二叉排序树的删除
(1)被删除的节点是叶子节点:直接删去该节点。 |
(2)被删除的节点只有左子树或者只有右子树,用其左子树或者 右子树替换它(节点替换)。 |
(3)被删除的节点既有左子树,也有右子树: 以其中序前趋值替换之(值替换),然后再删除该前趋节点。 前趋是左子树中最大的节点。 也可以用其后继替换之,然后再删除该后继节点。后继是右子树 中最小的节点。 |
二叉排序树的特点 |
二叉排序树的中序序列是一个递增有序序列 |
根节点的最左下节点是关键字最小的节点 |
根节点的最 右下节点是关键字最大的节点 |
2,平衡二叉树
(1)、什么是平衡二叉树
若一棵二叉树中每个节点的左、右子树的高度至多相差1,则称 此二叉树为平衡二叉树(AVL)。 平衡因子:该节点左子树的高度 - 右子树的高度。
(2)、平衡二叉树的插入调整
(1)LL型调整
LL型调整过程:
a, B节点带左子树α一起上升
b, A节点成为B的右孩子
c, 原来 B节点的右子树β作为A 的左子树
(2)RR型调整
RR型调整过程:
a, B 节点带右子树β一起上升
b, A节点成为B的左孩子
c, 原来 B节点的左子树α作为A 的右子树
(3)LR型调整
LR型调整过程:
a, C节点穿过A、B节点上升
b, B节点成为C的左孩子,A 节点成为C的右孩子
c, 原来 C节点的左子树β 作为 B的右子树;原来C节点的 右子树γ 作为A的左子树
(4)RL型调整
RL型调整过程:
a, C节点穿过A、B节点上升
b, B节点成为C的右孩子,A 节点成为C的左孩子
c, 原来 C节点的左子树β 作为 A的右子树;原来C节点的 右子树γ 作为B的左子树
练习:
含有n个节点的平衡二叉树的平均查找长度为O(log2n)。
3,B-树
B-树又称为多路平衡查找树,是一种组织和维护外存文 件系统非常有效的数据结构。
定义一棵m阶B:
1, 树中每个节点至多有m个孩子节点(即至多有m-1个关键字) 最多关键字个数Max = m-1 |
2, 除根节点外,其他非叶子节子点至少有[m/2](向上取整)个孩子节点,最少关键字个数Min = [m/2]-1 |
3, 若根节点不是叶子节点,则根节点至少有两个孩子节点 |
4, 每个节点的结构如下,节点中按关键字大小顺序排列 |
5, 所有外部节点都在同一层上。B-树是所有节点的平衡因子均 等于0的多路查找树 |
6, 一棵B-树中总有n个关键字,则外部节点个数为n+1(外部节点就是失败节点,指向它的指针为空,不含有任何信 息,是虚设的)。 |
元素的添加:
1, 插入节点有空位置,即关键字个数n<m-1:直接把关键字k 有序插入到该节点的合适位置上。
2, 插入节点没有空位置,即原关键字个数n=m-1 进行分裂
元素的删除:
1,加入删除节点在叶子节点上,观察删除后是否会出现下溢出,即关键字个数小于min,如果小于观察兄弟是否有多余的节点,若有借过来,如果没有,将父节点里面的关键字下放到兄弟节点里面,然后,在与兄弟节点进行合并
2,如果不是叶子节点,找该节点的前驱或者后驱,将其顶替
4,B+树
定义m阶B+树:
1, 每个分支节点至多有m棵子树 |
2, 有n棵子树的节点恰好有n个关键字。 |
3, 所有叶子节点包含全部关键字及指向相应记录的指针,而且叶子节点按关键字大小顺序链接。并将所有叶子节点链接起来。 |
4, 所有分支节点(可看成是索引的索引)中仅包含它的各个子节点 (即下级索引的索引块)中最大关键字及指向子节点的指针。 |
四,哈希查找
1,基本概念
哈希函数 | 把关键字为ki 的对象存放在相应的哈希地址中 |
哈希冲突 | 对于两个关键字分别为ki 和kj (i≠j)的记录,有ki ≠kj ,但h(ki )=h(kj )。 把这种现象叫做哈希冲突(同义词冲突) |
哈希表设计 | 与装填因子有关。装填因子α=存储的记录个数/哈希表的大小 =n/m α越小,冲突的可能性就越小;α越大(最大可取1), 冲突的可能性就越大。通常使最终的控制在0.6~0.9的范围内。 散列法的平均检索长度不随表中节点个数的增加而增加,而是随α的增加而增加的 |
与所采用的哈希函数有关 。好的哈希函数会减少冲突的发生;不 好的哈希函数会增加冲突的发生 | |
与解决冲突方法有关 。好的哈希冲突解决方法会减少冲突的发生。 |
2,哈希函数构造方法
1、直接定址法: 直接定址法是以关键字k本身或关键字加上某个数值常量c作为哈希地 址的方法。直接定址法的哈希函数h(k)为: h(k) = kx+b |
2、除留余数法:h(k)=k mod p ,p通常取小于等于表长的素数 |
3、数字分析法 |
3 哈希冲突解决方法
1、开放定址法
(1)线性探查法:d0 =h(k) => d i =(di-1 +1) mod m (1≤i≤m-1) |
(2)平方探查法: d0 =h(k) => d i =(d0 ± i^2) mod m (1≤i≤m-1) |
2、拉链法
拉链法是把所有的同义词用单链表链接起来的方法。