数据结构学习笔记-树

基本概念:树是 n ( n > = 0 ) n(n>=0) 结点的有限集

  1. 有且仅有一个特定的称为根的结点
  2. n > 1 n>1 时,其余结点可分为m个互不相交的有限集,每个集合都是一棵树,是根的子树。

其他概念:

  1. 结点的度:子树的个数;
  2. 树的度:树的节点中最大度
  3. 叶节点(终端结点):度为0的节点;而分支结点是度不为0的结点。
  4. 树的深度:树所有结点中最大层次(根节点的层次为1)
  5. 路径长度:结点个数-1,或者说是分支条数
  6. 兄弟结点是父结点相同的结点
  7. 森林是 m ( m > = 0 ) m(m>=0) 棵互不相交的树的集合

二叉树

二叉树是另一种树形结构,每个结点至多只有两棵子树,且有左右之分,需要注意的是,从树的概念衍生来的二叉树是可以为空树的。

性质

  1. 在二叉树的第 i i 层上至多有 2 i 1 2^{i-1} 个结点(i>=1)
  2. 深度为 k k 的二叉树至多有 2 k 1 2^k-1 个结点(k>=1),由此,深度为 k k 且有 2 k 1 2^k-1 个结点的二叉树是满二叉树;而完全二叉树是其 n n 个结点与满二叉树的 n ( n < = k ) n(n<=k) 个结点编号一致。
  3. 对任何一棵二叉树T,若叶结点数为 n 0 n_0 ,度为2的结点数为 n 2 n_2 ,则 n 0 = n 2 + 1 n_0=n_2+1
  4. 对于完全二叉树T,具有n个结点,其深度为 l o g 2 n + 1 log_2n+1
  5. 对于有 n n 个结点的完全二叉树,i为结点编号,如果 i = 1 i=1 i i 是二叉树的根,若 i > 1 i>1 则其双亲是 i / 2 i/2 (向下取整);另外,如果 2 i > n 2i>n i i 无左孩子, 2 i + 1 > n 2i+1>n i i 无右孩子

存储结构

  1. 顺序存储,以数组下标表示结点编号,明显可以看出,如果树不为完全二叉树,则浪费了很多存储空间
  2. 链式存储 分为数据域和左右指针域,链的头指针指向根节点,还有一种三叉链表,多加了一个指向双亲结点的指针。

二叉树的遍历和线索二叉树

遍历

  1. 前序遍历 根结点-左子结点-右子结点
  2. 中序遍历 左子结点-根结点-右子结点
  3. 后序遍历 左子结点-右子结点-根结点
    三种遍历方式正好对应波兰式,中缀表达式和逆波兰式
bool PreOrderTraverse(BinTree T)
{
	if (!T)
		return 1;
	else
	{
		Visit(T->data);
		PreOrderTraverse(T->left);
		PreOrderTraverse(T->right);
	}
	return 1;
}

遍历算法的不同之处仅仅为访问结点的先后关系,其实递归执行过程是完全一样的,仿照递归执行状态中递归栈的变化可写出相应的非递归算法,若栈顶记录的指针非空,则遍历左子树将左指针入栈;若栈顶记录的指针为空,说明应当返回上一层,若从右子树返回,不必保存当前的根指针,直接修改指针即可。

bool InOrderTraverse(BinTree T)
{
	InitStack(s);
	BinTree p=T;
	while(p||!isempty(s))
	{
		if(p)
		{
			Push(s,p);
			p=p->left;
		}
		else
		{
			Pop(s,p);
			if(!Visit(p->data))
				return 0;
			p=p->r;
		}
	}
	return 1;
}

猜你喜欢

转载自blog.csdn.net/sinat_34753172/article/details/83717897