STL笔记之树

树由节点(nodes)和边(edges)构成。整棵树有一个最上端节点,称为根节点(root)。每个节点可以有具方向性的边(directed edges),用来和其它节点相连。相连节点中,在上者为父节点(parent),在下者为子节点(child),无子节点者为叶节点(leaf)。子节点可以存在多个,如果最多只允许两个子节点,即所谓二叉树(binary tree)。不同结点如果拥有相同的父节点,则彼此互为兄弟节点(siblings)。根节点至任何节点之间有唯一途径(path),路径所经过的边数,称为路径长度(length)。根节点至任何一个节点的路径长度,即所谓该节点的深度(depth)。根节点的深度永远为0.某节点至最深子节点(叶节点)的路径长度,称为该节点的高度(height)。整棵树的高度,便以根节点的高度来表示。节点A->B之间如果存在(唯一)一条路径,那么A称为B的祖代(ancestor),B称为A的子代(descent)。任何节点的大小(size)是指其所有子代(包括自己)的节点总数。

二叉树搜索树(binary search tree)

二叉树,意义是任何节点最多只允许两个子节点,这两个子节点称为左子节点和右子节点。编译表达树(expression tree)和哈夫曼编码树(Huffman coding tree)都是二叉树。

二叉搜索树可提供对数时间的元素插入和访问。节点放置规则是:任何节点的键值一定大于其左子树中的每一个节点的键值,并小于右子树中每一个节点的键值。因此,从根节点一直往左走,直至无左路可走,即得最小元素,从根节点一直往右走,直至无右路可走,即得最大元素。

节点插入:从根结点开始,遇到键值较大则向左,遇到键值较小则向右,直到尾端,即插入点

节点删除:

  1. 无子节点,直接删除;
  2. 只有一个子节点,删除旧值,直接将其子节点连至其父节点;
  3. 有两个子节点,以右子树中的最小值取而代之(最小值可通过一直向左走到底获得)。

平衡二叉树(balanced binary search tree)

平衡的大致意义是:没有任何一个节点过深(深度过大)。

AVL树(Adelson-Velskii-Landis tree)

平衡因子:节点的左子树深度减去右子树深度。

要求:任何节点的左右子树高度相差最多为1。

平衡被破坏情况:设最深节点为X,X的左右两棵子树的高度相差2,即平衡因子绝对值大于1,分四种情况

  1. 插入点位于X的左子节点的左子树-左左;
  2. 插入点位于X的左子节点的右子树-左右;
  3. 插入点位于X的右子节点的左子树-右左;
  4. 插入点位于X的右子节点的右子树-右右。

1,4情况彼此对称,称为外侧插入,可采用单旋转操作调整解决;2,3情况彼此对称,称为内侧插入,可采用双旋转操作调整解决。

单旋转

情况1:以X为支点右旋

//             a                         b
//            / \                       / \
//           b   ar                   bl   a
//          / \          --->         /   / \
//        bl   br                    c   br  ar
//        /
//       c
//待插入节点为c,为情况1,需要进行右旋操作
void RRotate(BiTree& a)
{
	b = a->left;
	a->left = b->right;
	b->right = a;
	a->height = Max(Height(a->left), Height(a->right));
	b->height = Max(Height(b->left), Height(b->right));
	return b;
}

情况4:以X为支点左旋

//         a                         b
//        / \                       / \
//      al   b                     a   br
//          / \          --->     / \    \
//        bl   br                al  bl   c
//              \
//               c
//待插入节点为c,为情况4,需要进行左旋旋操作
void LRotate(BiTree& a)
{
	b = a->right;
	a->right = b->left;
	b->left = a;
	a->height = Max(Height(a->left), Height(a->right));
	b->height = Max(Height(b->left), Height(b->right));
	return b;
}

情况2,情况3:

//             a                      a                      c
//            / \                    / \                    / \
//           b   ar                 c   ar                 b   a
//          / \                    / \                    /\   /\
//         bl  c        ---->     b   cr      ---->      bl d cr ar
//            / \                / \
//           d   cr             bl  d
//待插入节点为d,为情况2,需要进行双旋转操作,先对a.left进行左旋,再对a进行右旋
void LRRotate(BiTree& a)
{
	a->left = LRotate(a->left);
	return RRotate(a);
}

//             a                       a                           c
//            / \                     / \                         /  \
//           al  b                  al   c                       a    b
//              / \                     / \                     / \  /  \
//             c   br   ---->          d   b     ---->         al d cr   br
//            / \                         / \
//           d   cr                      cr  br
//待插入节点为d,为情况3,需要进行双旋转操作,先对a.right右旋,再对a左旋
void RRRotate(BiTree& a)
{
	a->right = RRotate(a->right);
	return LRotate(a);
}

猜你喜欢

转载自blog.csdn.net/s_hit/article/details/79523863
今日推荐