第七章小结
第七章说实话,就像大梦初醒,一场梦结束之后,这一章就讲完了。可能我吸收的不是很好,所以在接下来的时间,好好的把知识点梳理一遍,做好总结。
(1)理一理本章的概念
关键字:关键字是数据元素中某个数据项的值。
查找表:动态查找表和静态查找表。动态查找表在查找的同时可以对表做修改操作(插入和删除等),静态查找表则不行。
平均查找长度:所有PiCi之和,P为查找概率,C为比较关键字的个数。
(2)顺序查找
数据元素的定义:
typedef struct{ KeyType key; //关键字域 InfoType otherinfo; //其他信息域 }ElemType;
顺序表的定义
typedef struct{ Elemtype *R;//存储空间的基地址 int Length;//当前长度 }SSTable;
顺序查找:设置哨兵查找的方法
int search_seq(SSTable ST,KeyType key) { ST.R[0].key=key;//哨兵 for(int i=ST.Length;ST.R[i].key!=key;--i);//从后往前找 return i; }
(3)折半查找
前提条件:线性表必须是采用顺序存储结构且有序排列。
int search_Bin(SSTable ST,KeyType key) { int low=1; int high=ST.Length; while(low<=high) { mid=(low+high)/2; if(key==ST.R[mid].key) return mid; else if(key<ST.R[mid].key) high=mid-1; //在前一子表查找 else low=mid+1; //在后一子表查找 } return 0; //在表中没有找到待查元素 }
折半查找法在查找成功时进行比较的关键字个数最多不超过树的深度。
(3)分块查找(索引顺序查找)
分块查找介于顺序查找和折半查找之间
(1)确定待查记录所在的块(顺序查找或折半查找)
(2)在块中顺序查找
分块查找优点:插入删除操作容易,无需大量移动。需要的存储空间增加一个索引表的空间
(4)二叉排序树(二叉查找树)
定义:(1)若左子树非空,则左子树的所有结点的值都小于它的根结点的值
(2)若右子树非空,则右子树所有结点的值都大于它的根结点的值。
(3)左右子树也都为二叉排序树
二叉排序树的递归查找(基于二叉链表存储):
BSTree searchBST(BSTree T,KeyType key) {//若查找成功,返回该结点的指针,否则返回空指针 if((!T)||key==T->data.key) return T; else if(key<T->data.key) return searchBST(T->lchild,key);//在左子树中查找 else return searchBST(T->rchild,key);//在右子树中查找 }
二叉排序树的插入(插入基于查找完成)和创建(创建是基于插入完成的)
void InsertBST(BSTree &T,ElemType e) { if(!T) { S=new BSTNode; S->data=e; S->lchild=S->rchild=NULL; T=S; } else if(e.key<T->data.key) InsertBST(T->lchild,e); //插入左子树 else if(e.key>T->data.key) InsertBST(T->rchild,e); //插入右子树 }
二叉排序树的创建
void createBST(BSTree &T) { T=NULL;//初始化为空树 cin>>e; while(e.key!=endflag) //endflag为自定义结束标志 { InsertBST(T,e);//插入二叉排序树中 cin>>e; } }
二叉排序树的删除:(1)删除结点为叶子结点,不改变树的结构,只需修改双亲结点的指针即可。
(2)删除结点只有左子树或只有右子树,则值要令其左子树或右子树直接成为其双亲结点的左子树即可。
f->lchild=p->lchild;(f->lchild=p->rchild)
(3)删除结点的左子树和右子树均不为空,(1)增加树的深度,令*P的左子树为F的左子树,*P的右子树为*S的右子树,以*S替代*P.(2)令*P的直接前驱或直接后继替代*P(以被删节点左子树中最大的关键字最大的结点替代被删节点)
(5)平衡二叉树(AVL树)
特点:(1)左子树和右子树的深度之差的绝对值不超过1,(2)左子树和右子树也是平衡二叉树
平衡因子:左子树和右子树的深度之差
创建平衡二叉树:基于二叉排序树处理,若破坏了平衡二叉树的特性,则对其进行调整:找到离插入结点最近的且平衡因子绝对值超过1,的祖先节点,以该节点为根的子树称为最小不平衡子树,将重新平衡的范围局限于这棵子树。
(6)B-树(平衡,有序,多路)
m叉树
(1)树中每个结点至多有m棵子树;
(2)若根结点不是叶子结点,则至少有两棵子树
(3)除根结点之外的所有非终端节点至少有m/2向上取整棵子树
(4)所有叶子结点出现在同一层次上,不带信息(为失败结点
(5)所有的非终端节点最多有m-1个关键字
(7)B+树
(1)有n棵子树的结点中有n个关键字
(2)所有叶子结点中包含全部关键字的信息
(3)所有非终端节点可以看成是索引
(8)散列表的查找(哈希查找)
(1)散列函数和散列地址:存储位置p和关键字key的一种对应关系,p=H(key),p为散列地址
(2)散列表:一个有限连续的地址空间(一维数组)
(3)冲突和同义词:对不同的关键字可能得到同一散列地址,这种现象称为冲突。具有相同函数值的关键字对该散列函数来说称作同义词。
构造散列函数:1,数字分析法(事先知道关键字集合)2,平方取中法,取关键字平方后中间几位或其组合作为散列地址(事先不知道散列表的情况)
3,折叠法,将关键字分割成位数相同的几部分,然后取这几部分的叠加和作为散列地址(适于散列地址的位数较少,关键之位数较多的)*4,除留余数法,H(key)=key%p,p为不大于表长的数。(一般为质数)
处理冲突:1.开放地址法(会产生二次聚集):Hi=(H(key)+di)%m i=1,2,3...,k(k<=m-1)(1)线性探测法(想象为循环表)发生冲突时,从冲突地址的下一单元顺序寻找空单元,若找到最后的单元也没找到,则返回表头继续寻找,知道找到空位。找不到,则溢出处理(2)二次探测法di=12,-12,22,-22,...(3)伪随机探测法,di=伪随机序列
2,链地址法(类与邻接表结构,不会产生二次聚集)
散列表的查找(开放地址法):
#define m 20 typedef struct { keytype key; infotype otherinfo; }HashTable[m]; int searchHash(HashTable HT,keytype key) { h0=H(key);//根据散列函数计算散列地址 if(HT[h0].key==0)return -1; //若h0为空,则所查元素不存在 else if(HT[h0].key==key) return h0; else{ for(i=1;i<m;++i) { hi=(h0+i)%m; //按照线性探测法计算下一个散列地址 if(HT[hi].key==0)return -1; //若hi为空,则所查元素不存在 else if(HT[hi].key==key) return hi; } return -1; } }
上一次的目标完成一半,另一半好好学习第七章,这个还有待提高,第七章没有学的很好。作业还没有做出来,所以接下来,就是把第七章作业完成,并好好复习第七章,还有第六章的错题回顾。