数据结构与算法[1]-平衡二叉树-C#版
来源:互联网 发布:做淘宝创业家破人亡 编辑:程序博客网 时间:2024/04/30 01:23
平衡二叉树
形态匀称的二叉树称为平衡二叉树 (Balanced binary tree) ,其严格定义是:
一棵空树是平衡二叉树;若 T 是一棵非空二叉树,其左、右子树为 TL 和 TR ,令 hl 和 hr 分别为左、右子树的深度。当且仅当
①TL 、 TR 都是平衡二叉树;
② | hl - hr |≤ 1;
时,则 T 是平衡二叉树。
【例】如图 8.4 所示。
(a)平衡二叉树 (b)非平衡二叉树
图8.3 平衡二叉树与非平衡二叉树
相应地定义 hl - hr 为二叉平衡树的平衡因子 (balance factor) 。因此,平衡二叉树上所有结点的平衡因子可能是 -1 , 0 , 1 。换言之,若一棵二叉树上任一结点的平衡因子的绝对值都不大于 1 ,则该树是就平衡二叉树。
动态平衡技术
1.动态平衡技术
Adelson-Velskii 和 Landis 提出了一个动态地保持二叉排序树平衡的方法,其基本思想是:
在构造二叉排序树的过程中,每当插入一个结点时,首先检查是否因插入而破坏了树的平衡性,如果是因插入结点而破坏了树的平衡性,则找出其中最小不平衡子树,在保持排序树特性的前提下,调整最小不平衡子树中各结点之间的连接关系,以达到新的平衡。通常将这样得到的平衡二叉排序树简称为 AVL 树。
2.最小不平衡子树
以离插入结点最近、且平衡因子绝对值大于 1 的结点作根结点的子树。为了简化讨论,不妨假设二叉排序树的最小不平衡子树的根结点为 A ,则调整该子树的规律可归纳为下列四种情况:
(1) LL 型:
新结点 X 插在 A 的左孩子的左子树里。调整方法见图 8.5(a) 。图中以 B 为轴心,将 A 结点从 B 的右上方转到 B 的右下侧,使 A 成为 B 的右孩子。
图8.5 平衡调整的4种基本类型(结点旁的数字是平衡因子)
(2)RR 型:
新结点 X 插在 A 的右孩子的右子树里。调整方法见图 8.5(b) 。图中以 B 为轴心,将 A 结点从 B 的左上方转到 B 的左下侧,使 A 成为 B 的左孩子。
(3)LR 型:
新结点 X 插在 A 的左孩子的右子树里。调整方法见图 8.5(c) 。分为两步进行:第一步以 X 为轴心,将 B 从 X 的左上方转到 X 的左下侧,使 B 成为 X 的左孩子, X 成为 A 的左孩子。第二步跟 LL 型一样处理 ( 应以 X 为轴心 ) 。
(4)RL 型:
新结点 X 插在 A 的右孩子的左子树里。调整方法见图 8.5(d) 。分为两步进行:第一步以 X 为轴心,将 B 从 X 的右上方转到 X 的右下侧,使 B 成为 X 的右孩子, X 成为 A 的右孩子。第二步跟 RR 型一样处理 ( 应以 X 为轴心 ) 。
实现代码:
- /// <summary>
- /// balance binary node
- /// </summary>
- class AVLBinaryNode
- {
- //field
- private AVLBinaryNode lChild;
- private AVLBinaryNode rChild;
- private AVLBinaryNode parent;
- private int data;
- //property
- /// <summary>
- /// get or set left child of node
- /// </summary>
- public AVLBinaryNode LChild
- {
- get
- {
- return lChild;
- }
- set
- {
- lChild = value;
- }
- }
- /// <summary>
- /// get or set right child of node
- /// </summary>
- public AVLBinaryNode RChild
- {
- get
- {
- return rChild;
- }
- set
- {
- rChild = value;
- }
- }
- /// <summary>
- /// get or set parent of node
- /// </summary>
- public AVLBinaryNode Parent
- {
- get
- {
- return parent;
- }
- set
- {
- parent = value;
- }
- }
- /// <summary>
- /// get or set date of node
- /// </summary>
- public int Data
- {
- get
- {
- return data;
- }
- set
- {
- data = value;
- }
- }
- /// <summary>
- /// create new AVLBinaryNode instance
- /// </summary>
- public AVLBinaryNode(AVLBinaryNode lChild,AVLBinaryNode rChild,AVLBinaryNode parent,int data)
- {
- this.lChild = lChild;
- this.rChild = rChild;
- this.parent = parent;
- this.data = data;
- }
- }
- //-------------------------------------------------------------
- /// <summary>
- /// balance binary of tree
- /// </summary>
- class AVLBinaryTree
- {
- private AVLBinaryNode rootHead;
- /// <summary>
- /// create balance of binary
- /// </summary>
- /// <param name="dates">ordered datas</param>
- public AVLBinaryTree(int[] datas)
- {
- //load first node
- rootHead = new AVLBinaryNode(null, null, null, datas[0]);
- for (int i = 1; i < datas.Length; i++)
- {
- InsertNode(datas[i]);
- }
- }
- /// <summary>
- /// insert new node
- /// </summary>
- /// <param name="newNode">new node</param>
- public void InsertNode(int data)
- {
- AVLBinaryNode pTemp = this.rootHead;
- AVLBinaryNode previousNode = null;
- bool isLeft = true;
- while (pTemp != null)
- {
- if (pTemp.Data > data)
- {
- if (pTemp.LChild == null)
- {
- previousNode = pTemp;
- isLeft = true;
- }
- pTemp = pTemp.LChild;
- }
- else if (pTemp.Data < data)
- {
- if (pTemp.LChild == null)
- {
- previousNode = pTemp;
- isLeft = false;
- }
- pTemp = pTemp.RChild;
- }
- else
- {
- return;
- }
- }
- if (isLeft)
- {
- previousNode.LChild = new AVLBinaryNode(null, null, previousNode, data);
- }
- else
- {
- previousNode.LChild = new AVLBinaryNode(null, null, previousNode, data);
- }
- int leftDepth = GetDepthOfTree(rootHead.LChild);
- int rightDepth = GetDepthOfTree(rootHead.RChild);
- if ((leftDepth - rightDepth) > 1 || (leftDepth - rightDepth) < -1)//judge for whether convert
- {
- //judge convert type
- int iType = GetConvertType(previousNode.Parent);
- switch (iType)
- {
- case 1:
- this.LLConvert(previousNode.Parent);
- break;
- case 2:
- this.RRConvert(previousNode.Parent);
- break;
- case 3:
- this.LRConvert(previousNode.Parent);
- break;
- case 4:
- this.RLConvert(previousNode.Parent);
- break;
- default:
- break;
- }
- }
- }
- /// <summary>
- /// will "LL" convert validate VAL tree
- /// </summary>
- /// <param name="rootnNode">root node of sub unbalance/param>
- public void LLConvert(AVLBinaryNode rootNode)
- {
- AVLBinaryNode nTemp = rootNode.Parent;
- rootNode.Parent = rootNode.LChild;
- rootNode.LChild.RChild = rootNode;
- if (nTemp.LChild == rootNode)
- {
- nTemp.LChild = rootNode.LChild;
- }
- else
- {
- nTemp.RChild = rootNode.LChild;
- }
- rootNode.LChild.Parent = nTemp;
- rootNode.LChild = null;
- }
- /// <summary>
- /// will "RR" convert validate VAL tree
- /// </summary>
- /// <param name="rootnNode">root node of sub unbalance</param>
- public void RRConvert(AVLBinaryNode rootNode)
- {
- AVLBinaryNode nTemp = rootNode.Parent;
- rootNode.Parent = rootNode.RChild;
- rootNode.RChild.LChild = rootNode;
- if (nTemp.LChild == rootNode)
- {
- nTemp.LChild = rootNode.RChild;
- }
- else
- {
- nTemp.RChild = rootNode.RChild;
- }
- rootNode.RChild.Parent = nTemp;
- rootNode.RChild = null;
- }
- /// <summary>
- /// will "LR" convert validate VAL tree
- /// </summary>
- /// <param name="rootnNode">root node of sub unbalance</param>
- public void LRConvert(AVLBinaryNode rootNode)
- {
- AVLBinaryNode nTemp = rootNode.Parent;
- rootNode.Parent = rootNode.LChild.RChild;//设置1结点的父结点
- rootNode.LChild.Parent = rootNode.LChild.RChild;//设定2结点的父结点
- rootNode.LChild.RChild.LChild = rootNode.LChild;//设置3结点的左孩子
- rootNode.LChild.RChild.RChild = rootNode;//设置3结点的右孩子
- rootNode.LChild.RChild.RChild.Parent = nTemp;//设置第3个结点的父结点
- if (nTemp.LChild == rootNode)//设置3结点在父结点的左孩子还是右孩子
- {
- nTemp.LChild = rootNode.LChild.RChild.RChild;
- }
- else
- {
- nTemp.RChild = rootNode.LChild.RChild.RChild;
- }
- rootNode.LChild.RChild = null;
- rootNode.LChild = null;
- }
- /// <summary>
- /// will "RL" convert validate VAL tree
- /// </summary>
- /// <param name="rootnNode">root node of sub unbalance</param>
- public void RLConvert(AVLBinaryNode rootNode)
- {
- AVLBinaryNode nTemp = rootNode.Parent;
- rootNode.Parent = rootNode.RChild.LChild;//设置1结点的父结点
- rootNode.RChild.Parent = rootNode.RChild.LChild;//设定2结点的父结点
- rootNode.RChild.LChild.RChild = rootNode.RChild;//设置3结点的左孩子
- rootNode.RChild.LChild.LChild = rootNode;//设置3结点的右孩子
- rootNode.RChild.LChild.LChild.Parent = nTemp;//设置第3个结点的父结点
- if (nTemp.LChild == rootNode)//设置3结点在父结点的左孩子还是右孩子
- {
- nTemp.LChild = rootNode.RChild.LChild.LChild;
- }
- else
- {
- nTemp.RChild = rootNode.RChild.LChild.LChild;
- }
- rootNode.RChild.LChild = null;
- rootNode.RChild = null;
- }
- /// <summary>
- /// check convert Type (1 is LL,2 is RR,3 is LR,4 is RL,0 is other)
- /// </summary>
- /// <param name="rootNode"></param>
- /// <returns></returns>
- private int GetConvertType(AVLBinaryNode rootNode)
- {
- int iType = 0;
- if (rootNode != null)
- {
- if (rootNode.LChild != null && rootNode.RChild == null)
- {
- if (rootNode.LChild.LChild != null && rootNode.LChild.RChild == null)
- {
- iType = 1;
- }
- else if (rootNode.LChild.LChild == null && rootNode.LChild.RChild != null)
- {
- iType = 3;
- }
- }
- else if (rootNode.RChild != null && rootNode.LChild == null)
- {
- if (rootNode.RChild.RChild != null && rootNode.RChild.LChild == null)
- {
- iType = 2;
- }
- else if (rootNode.RChild.LChild != null && rootNode.RChild.RChild == null)
- {
- iType = 4;
- }
- }
- }
- return iType;
- }
- /// <summary>
- /// get pointer tree depth
- /// </summary>
- /// <param name="rootNode">pointer tree root node</param>
- /// <returns></returns>
- public int GetDepthOfTree(AVLBinaryNode rootNode)
- {
- int depthCount = 0;
- AVLBinaryNode nodeTemp = null;
- System.Collections.Stack stack = new System.Collections.Stack();
- if (rootHead != null)
- {
- stack.Push(nodeTemp);
- while (stack.Count != 0)
- {
- //gain max depth count
- depthCount = depthCount < stack.Count ? stack.Count : depthCount;
- if (nodeTemp.LChild != null)
- {
- stack.Push(nodeTemp.LChild);
- }
- nodeTemp = (AVLBinaryNode)stack.Pop();
- if (nodeTemp.RChild != null)
- {
- stack.Push(nodeTemp.RChild);
- }
- }
- depthCount += 1;
- }
- return depthCount;
- }
- }
- 数据结构与算法[1]-平衡二叉树-C#版
- C#与数据结构--树论--平衡二叉树(AVL Tree)
- C#与数据结构--树论--平衡二叉树(AVL TREE)
- C#与数据结构--树论--平衡二叉树(AVL Tree)
- C#与数据结构--树论--平衡二叉树(AVL Tree)
- C#与数据结构--树论--平衡二叉树(AVL TREE)
- 数据结构与算法系列----平衡二叉树(AVL树)
- 数据结构与算法问题 AVL二叉平衡树
- 数据结构与算法10: 平衡二叉树AVL(AVL Tree)
- 【数据结构与算法】数组和单链表转平衡二叉树
- 数据结构与算法分析 c++ 平衡二叉树 AvlTree
- 数据结构与算法分析之平衡二叉树的建立
- 数据结构与算法(C#实现)---二叉树
- 数据结构与算法(C#实现)---二叉树
- 【数据结构】算法9.9-9.12 平衡二叉树
- 数据结构和算法一:平衡二叉树
- 数据结构与算法分析笔记与总结(java实现)--二叉树13:平衡二叉树
- 数据结构与算法7:哈夫曼树,二叉查找树,平衡二叉查找树,B树,B+树
- j2me 点滴16
- j2me 点滴16
- 正则表达式之道(转载)
- j2me 点滴17
- 处理表重复记录
- 数据结构与算法[1]-平衡二叉树-C#版
- DataInputStream 的readInt 算法
- sql 生成 唯一表示 (NewID( )) ,行号。
- 程序循环的使用
- Java 文本控件内容录入限制(含源代码说明)(二)
- 设计模式 之 单件模式
- 文本控件内容录入限制(含源代码说明)(一)
- Linux 卸载JAVA
- 自制的一个输入验证控件