二叉树

 

二叉树

二叉树基本性质
  1. 第 i 层:至多 2^(i-1) 个结点
  2. 深度为k,至多 2^k - 1 个结点,至少 k 个结点
  3. 叶子n0个,度为2的结点n2个:n0 = n2 + 1
  4. 完全二叉树:n个结点,则深度为 [ log2(n)] + 1
  5. 完全二叉树(顺序表存储,下标从1开始)下标关系:双亲[ i / 2 、左孩子 2 * i 、右孩子 2 * i + 1
 
存储结构
顺序存储
二叉链表
三叉链表
线索链表
 
 
 
二叉树实现(二叉链表
二叉树结点
  1.     publicclassBiNode{
  2.         char data;
  3.         BiNode left;
  4.         BiNode right;
  5.         int flag =0;//供非递归后序遍历使用
  6.     }
初始化
  1.     privatestaticint i;
  2.     publicBinaryTree(char[] pre){
  3.         i =0;
  4.         root = create(pre);
  5.     }
  6.  
  7.     //初始化(先序遍历顺序存放数组、'#'表示null)
  8.     privateBiNode create(char[] pre)
  9.     {
  10.         if(i < pre.length)
  11.         {
  12.             if(pre[i]=='#')                             //结点为空
  13.             {
  14.                 i++;
  15.                 return null;
  16.             }
  17.  
  18.             BiNode p =newBiNode(pre[i], null, null);    //结点非空
  19.             i++;
  20.             p.left = create(pre);                         //递归建立左子树
  21.             p.right = create(pre);                       //递归建立右子树
  22.             return p;
  23.         }
  24.         return null;
  25.     }
遍历(递归)
  • 先序遍历
  1.     publicvoid preOrder(){
  2.         preOrder(root);
  3.     }
  4.     privatevoid preOrder(BiNode root){
  5.         if(root == null)return;
  6.  
  7.         System.out.print(root.data);       //访问结点
  8.         preOrder(root.left);
  9.         preOrder(root.right);
  10.     }
  • 中序遍历
  1.    publicvoid inOrder(){
  2.         inOrder(root);
  3.     }
  4.     privatevoid inOrder(BiNode root){
  5.         if(root == null)return;
  6.  
  7.         inOrder(root.left);
  8.         System.out.print(root.data);      //访问结点
  9.         inOrder(root.right);
  10.     }
  • 后序遍历
  1.     publicvoid postOrder(){
  2.         postOrder(root);
  3.     }
  4.     privatevoid postOrder(BiNode root){
  5.         if(root == null)return;
  6.  
  7.         postOrder(root.left);
  8.         postOrder(root.right);
  9.         System.out.print(root.data);     //访问结点
  10.     }
  • 层序遍历
  1.     publicvoid levelOrder(){
  2.         levelOrder(root);
  3.     }
  4.     privatevoid levelOrder(BiNode root){
  5.         LinkedList<BiNode>queue=newLinkedList<BiNode>();  //LinkedList实现了Queue接口
  6.  
  7.         BiNode p = root;
  8.         while(p != null){
  9.             System.out.print(p.data);    //访问结点
  10.  
  11.             if(p.left != null)
  12.                 queue.add(p.left);
  13.             if(p.right != null)
  14.                 queue.add(p.right);
  15.  
  16.             p =queue.poll();           //队头出队并返回为p
  17.         }
  18.     }
 
遍历(非递归)
  • 先序遍历
  1.     privatevoid preOrder(BiNode head){
  2.         LinkedList<BiNode> s =newLinkedList<BiNode>();
  3.  
  4.         while(head != null ||!s.isEmpty())
  5.         {
  6.             while(head != null)                //访问左子树
  7.             {
  8.                 System.out.print(head.data);    //访问左子树
  9.                 s.push(head);                    //结点入栈(待后面找其右子树使用)= =(“递归”)
  10.                 head = head.left;
  11.             }
  12.  
  13.             if(!s.isEmpty())                   //转向右子树
  14.             {
  15.                 head = s.peek().right;     //转向右子树
  16.                 s.pop();                        //结点出栈(已经找到其右子树)= =(“递归结束”)
  17.             }
  18.         }
  19.     }
 
 
 
  • 中序遍历
  1.     privatevoid inOrder2(BiNode head){
  2.         LinkedList<BiNode> s =newLinkedList<BiNode>();
  3.  
  4.         while(head != null ||!s.isEmpty())
  5.         {
  6.             while(head != null)                //左子树入栈
  7.             {
  8.                 s.push(head);                    //结点入栈(待后面找其右子树使用)= =(“递归”)
  9.                 head = head.left;
  10.             }
  11.  
  12.             System.out.print(s.peek().data);    //访问左子树
  13.  
  14.             if(!s.isEmpty())                   //转向右子树
  15.             {
  16.                 head = s.peek().right;         //转向右子树
  17.                 s.pop();                        //结点出栈(已经找到其右子树)= =(“递归结束”)
  18.             }
  19.         }
  20.     }
 
 
  • 后序遍历
  1.     //后序遍历特点:递归左右子树后,还需访问结点:
  2.     //1、左子树入栈
  3.     //2、“两次出栈”(用flag标记模仿):第一次是为了找到左子树相应的右子树结点;第二次是为了访问结点
  4.     privatevoid postOrder2(BiNode head){
  5.         LinkedList<BiNode> s =newLinkedList<BiNode>();
  6.  
  7.         while(head != null ||!s.isEmpty())
  8.         {
  9.             while(head != null)                        //左子树入栈
  10.             {
  11.                 head.flag =1;
  12.                 s.push(head);                            //结点连同flag入栈(待后面找其右子树使用)= =(“递归”)
  13.                 head = head.left;
  14.             }
  15.  
  16.             while(!s.isEmpty()&& s.peek().flag ==2)  //若flag为2(已经找到其右子树出过一次栈),访问结点
  17.             {
  18.                 System.out.print(s.peek().data);       //访问结点元素
  19.                 s.pop();                               //(第二次“结点出栈”)实际结点出栈(已经访问结点元素)= =(“递归结束”)
  20.             }
  21.  
  22.             if(!s.isEmpty())                         //flag为1,转向右子树
  23.             {
  24.                 head = s.peek().right;                //转向右子树
  25.                 s.peek().flag =2;                    //(第一次“flag模拟出栈”)标记为2,但实际结点不出栈(已经找到其右子树)
  26.             }
  27.  
  28.         }
  29.     }
插入
  1.   //在p结点后插入data
  2.     publicvoid insert(BiNode p,char data, boolean left){
  3.         if(p != null){
  4.             if(left)                //插入位置为左孩子
  5.                 p.left =newBiNode(data,p.left,null);
  6.             else                   //插入位置为右孩子
  7.                 p.right =newBiNode(data,p.right,null);
  8.         }
  9.     }
 
删除
  1.     //删除p的一个子树
  2.     publicvoiddelete(BiNode p, boolean left){
  3.         if(p != null){
  4.             if(left)              //删除目标为左子树
  5.                 p.left = null;
  6.             else                  //删除目标为右子树
  7.                 p.right = null;
  8.         }
  9.     }
 
 

哈夫曼树(最优二叉树)

哈夫曼树的存储结构:
哈夫曼算法:
 


一般树的存储结构

  • 双亲表示法:
 
  • 孩子表示法:
1、多重链表表示法
2、孩子链表表示法
 
  • 双亲孩子表示法:
 
  • 孩子兄弟表示法:
 

树与森林的转换

 
 
 
 

整理by Doing

参考资料:《数据结构(C++版)》王红梅

原文地址:https://www.cnblogs.com/Doing-what-I-love/p/5535020.html