数据结构(4)

树,二叉树,查找算法总结

一.思维导图


二.重要概念笔记

1.树

查找类:
Root(T) //求树的根结点
Value(T, cur_e) //求当前结点的元素值
Parent(T, cur_e) //求当前结点的双亲结点
LeftChild(T, cur_e) //求当前结点的最左孩子
RightSibling(T, cur_e)//求当前结点的右兄弟
TreeEmpty(T) // 判定树是否为空树
TreeDepth(T) // 求树的深度
TraverseTree(T) //遍历
插入:
InitTree(&T) // 初始化置空树
CreateTree(&T, definition) // 按定义构造
Assign(T, cur_e, value)   // 给当前结点赋值
InsertChild(&T, &p, i, c) // 将以c为根的树插入为结点p的第i棵子树
删除:
ClearTree(&T) //将树清空
DestroyTree(&T) //销毁树的结构
DeleteChild(&T,&p,i)//删除结点p的第i个孩子

2.二叉树

① 两类特殊的二叉树:

满二叉树:指的是深度为k且含有2k-1个结点的二

叉树。

完全二叉树:树中所含的n个结点和满二叉树中

编号为 1 至 n的结点一一对应。

②完全二叉树具有n个结点的完全二叉树的深度为 log2n+1

③算法递归

void Preorder(BiTree T)
{ //先序遍历二叉树
	if (T) {
		cout << T->data; // 访问结点
		Preorder(T->lchild); // 遍历左子树
		Preorder(T->rchild); // 遍历右子树
	}
}
void Inorder(BiTree T)
{ // 中序遍历二叉树
	if (T) {
		Inorder(T->lchild); // 遍历左子树
		cout << T->data; // 访问结点
		Inorder(T->rchild); // 遍历右子树
	}
}
void Postorder(BiTree T)
{ // 后序遍历二叉树
	if (T) {
		Postorder(T->lchild); // 遍历左子树
		Postorder(T->rchild); // 遍历右子树
		cout << T->data; // 访问结点
	}
}

④非递归算法

⑤线索链表的遍历算法:

如何找到下一节点? 

for(p = firstNode(T);p;p = Succ(p)) 

Visit(p);

⑥中序线索化链表的遍历算法

1.中序遍历的第一个结点 :左子树上处于“最左下”(没有左子树)的结点。

2.在中序线索化链表中结点的后继 :

若无右子树,则为后继线索所指结点;否则为对其右子树进行中序遍历时访问的第一个结点。

⑧树、二叉树、森林的相互转化

  1. 树转换为二叉树
    1)加线:在所有相邻的兄弟之间各加一连线
    2)抹线:每个非终端结点只保留它到最左孩
    子的连线,去除它与其余孩子之间的连线;
    3)旋转调整:以根结点为轴心,顺时针旋转
    一定角度,使结点按层次排列
  2. 二叉树转换为树
    1)加线:若p结点是双亲结点的左孩子,则将p的右孩子、右孩子的
    右孩子、…….沿分支找到的所有右孩子,都与p的双亲用线连起来
    2)抹线:抹掉原二叉树中双亲与右孩子之间的连线
  1. 调整:将结点按层次排列
  1. 森林转换为二叉树
    1.转换:将各棵树分别转成二叉树;
    2.加线:把每棵树的根结点用线连起来;
    3.调整:以第一棵树的根结点作为二叉
    树的根结点,将结点按层次排列

⑨构造哈夫曼树

三.查找

①顺序表查找

int Search_Seq(SSTable ST, KeyType key) {

	ST.elem[0].key = key; 
	// 从后往前找
	for (i = ST.length; ST.elem[i].key != key; --i);
	return i; 

②有序表查找:时间复杂度O(log2n)

int Search_Bin(SSTable ST, KeyType key) {
	low = 1; high = ST.length; // 置区间初值
	while (low <= high) {
		mid = (low + high) / 2;
		if (EQ(key, ST.elem[mid].key) )
		return mid; // 找到待查元素
		else if (LT(key, ST.elem[mid].key))
			high = mid - 1; // 继续在前半区间进行查找
		else low = mid + 1; // 继续在后半区间进行查找
	}
	return 0; // 顺序表中不存在待查元素
} 

二叉排序树查找性能分析含有n个结点的二叉排序树的平均查找长度和树的形态有关

④B-树的查找:

从根结点出发,沿指针搜索结点和在结点内进行顺序(或折半)查找两个过程交叉进行;

若查找成功,则返回指向被查关键字所在结点的指针和关键字在结点中的位置;若查找不成功,则返回插入位置。

Result SearchBTree(BTree T, KeyType K) {
	p = T; q = NULL; found = FALSE; i = 0;
	while (p && !found) {
		i = Search(p, K);
		// 在p->key[1..keynum]中查找 i ,p->key[i]<=K<p->key[i+1]
		if (i > 0 && p->key[i] == K) found = TRUE;
		else { q = p; p = p->ptr[i]; } // q 指示 p 的双亲
	}
	if (found) return (p, i, 1); // 查找成功
	else return (q, i, 0); // 查找不成功
} // SearchBTree

⑤B-树的插入

⑥B-树的删除

首先必须找到待删关键字所在结点,并且要求删除之后,结点中关键字的个数不能小于[m/2]-1;

否则, 要从其左(或右)兄弟结点“借调”关键字,若其左和右兄弟结点均无关键字可借(结点中只有最少量的关键字),则必须进行结点的“合并”。

⑦B+树

1.每个分支节点至多有m棵子树

2.根节点或者没有子树,或者至少有两棵子树

3.除根节点,其他每个分支节点至少有[m/2]棵子树;

4.有n棵子树的节点有n个关键字

5.叶子节点包含全部关键字及指向相应记录的指针

6.所有分支节点(可看成是分块索引的索引表)

⑧哈希函数构造方法

直接定址法、数字分析法、平方取中法、折叠法 、除留余数法、随机数法

!除留余数法:

设定哈希函数为:H(key) = key MOD p

其中,p≤m (表长) 并且p应为不大于 m 的素数或是不含 20 以下的质因子

⑨处理冲突方法

开放定址法 、再哈希法、链地址法、建立公共溢出区

1.开放地址法:线性探测再散列、二次探测再散列、随机探测再散列

2.链地址法(拉链法):将所有哈希地址相同的记录都链接在同一链表中

⑩哈希表的查找

Status SearchHash(HashTable H, KeyType K) {

	H0 = Hash(K); // 求得哈希地址H0
	if (HT[H0].key == NULLKEY) return -1;
	else if (HT[H0].key == key) return H0;
	else {
		for (int i = 1; i < m; i++) {
			Hi = collision(H0, i);//利用再探测方法确定Hi
			if (HT[Hi].key == NULLKEY) return -1;
			else if (HT[Hi].key == key) return Hi;//找到
		}
		return -1;
	}
} 

三.疑难解惑

平衡二叉树中插入新节点的调整:

不太理解课堂上的平衡旋转,这种调整更直观易懂



posted @ 2020-04-25 21:10  Styoool(曾广芝)  阅读(247)  评论(0)    收藏  举报