zoukankan      html  css  js  c++  java
  • 数据结构与算法——二叉树(1)

    二叉树节点结构

    class Node< V > {
    		V value;
    		Node left;
    		Node right;
    }
    

    用递归和非递归两种方式实现二叉树的先序、中序、后序遍历

    import java.util.Stack;
    
    public class PreInPosTraversal {
    
    	public static class Node {
    		public int value;
    		public Node left;
    		public Node right;
    
    		public Node(int data) {
    			this.value = data;
    		}
    	}
    
    	public static void preOrderRecur(Node head) {
    		if (head == null) {
    			return;
    		}
    		System.out.print(head.value + " ");
    		preOrderRecur(head.left);
    		preOrderRecur(head.right);
    	}
    
    	public static void inOrderRecur(Node head) {
    		if (head == null) {
    			return;
    		}
    		inOrderRecur(head.left);
    		System.out.print(head.value + " ");
    		inOrderRecur(head.right);
    	}
    
    	public static void posOrderRecur(Node head) {
    		if (head == null) {
    			return;
    		}
    		posOrderRecur(head.left);
    		posOrderRecur(head.right);
    		System.out.print(head.value + " ");
    	}
    	
        //非递归序列
    	public static void preOrderUnRecur(Node head) {
    		System.out.print("pre-order: ");
    		if (head != null) {
    			Stack<Node> stack = new Stack<Node>();
    			stack.add(head);
    			while (!stack.isEmpty()) {
    				head = stack.pop();
    				System.out.print(head.value + " ");
    				if (head.right != null) {
    					stack.push(head.right);
    				}
    				if (head.left != null) {
    					stack.push(head.left);
    				}
    			}
    		}
    		System.out.println();
    	}
    	//先压左再压右
    	public static void inOrderUnRecur(Node head) {
    		System.out.print("in-order: ");
    		if (head != null) {
    			Stack<Node> stack = new Stack<Node>();
    			while (!stack.isEmpty() || head != null) {
    				if (head != null) {
    					stack.push(head);
    					head = head.left;
    				} else {
    					head = stack.pop();
    					System.out.print(head.value + " ");
    					head = head.right;
    				}
    			}
    		}
    		System.out.println();
    	}
    
    	public static void posOrderUnRecur1(Node head) {
    		System.out.print("pos-order: ");
    		if (head != null) {
    			Stack<Node> s1 = new Stack<Node>();
    			Stack<Node> s2 = new Stack<Node>();
    			s1.push(head);
    			while (!s1.isEmpty()) {
    				head = s1.pop();
    				s2.push(head);
    				if (head.left != null) {
    					s1.push(head.left);
    				}
    				if (head.right != null) {
    					s1.push(head.right);
    				}
    			}
    			while (!s2.isEmpty()) {
    				System.out.print(s2.pop().value + " ");
    			}
    		}
    		System.out.println();
    	}
    	
    	public static void posOrderUnRecur2(Node h) {
    		System.out.print("pos-order: ");
    		if (h != null) {
    			Stack<Node> stack = new Stack<Node>();
    			stack.push(h);
    			Node c = null;
    			while (!stack.isEmpty()) {
    				c = stack.peek();
    				if (c.left != null && h != c.left && h != c.right) {
    					stack.push(c.left);
    				} else if (c.right != null && h != c.right) {
    					stack.push(c.right);
    				} else {
    					System.out.print(stack.pop().value + " ");
    					h = c;
    				}
    			}
    		}
    		System.out.println();
    	}
    
    	public static void main(String[] args) {
    		Node head = new Node(5);
    		head.left = new Node(3);
    		head.right = new Node(8);
    		head.left.left = new Node(2);
    		head.left.right = new Node(4);
    		head.left.left.left = new Node(1);
    		head.right.left = new Node(7);
    		head.right.left.left = new Node(6);
    		head.right.right = new Node(10);
    		head.right.right.left = new Node(9);
    		head.right.right.right = new Node(11);
    
    		// recursive
    		System.out.print("pre-order: ");
    		preOrderRecur(head);
    		System.out.println();
    		System.out.print("in-order: ");
    		inOrderRecur(head);
    		System.out.println();
    		System.out.print("pos-order: ");
    		posOrderRecur(head);
    		System.out.println();
    
    		// unrecursive
    		preOrderUnRecur(head);
    		inOrderUnRecur(head);
    		posOrderUnRecur1(head);
    		posOrderUnRecur2(head);
    	}
    }
    

    如何直观的打印一颗二叉树

    public class PrintBinaryTree {
    
    	public static class Node {
    		public int value;
    		public Node left;
    		public Node right;
    
    		public Node(int data) {
    			this.value = data;
    		}
    	}
    
    	public static void printTree(Node head) {
    		System.out.println("Binary Tree:");
    		printInOrder(head, 0, "H", 17);
    		System.out.println();
    	}
    
    	public static void printInOrder(Node head, int height, String to, int len) {
    		if (head == null) {
    			return;
    		}
    		printInOrder(head.right, height + 1, "v", len);
    		String val = to + head.value + to;
    		int lenM = val.length();
    		int lenL = (len - lenM) / 2;
    		int lenR = len - lenM - lenL;
    		val = getSpace(lenL) + val + getSpace(lenR);
    		System.out.println(getSpace(height * len) + val);
    		printInOrder(head.left, height + 1, "^", len);
    	}
    
    	public static String getSpace(int num) {
    		String space = " ";
    		StringBuffer buf = new StringBuffer("");
    		for (int i = 0; i < num; i++) {
    			buf.append(space);
    		}
    		return buf.toString();
    	}
    
    	public static void main(String[] args) {
    		Node head = new Node(1);
    		head.left = new Node(-222222222);
    		head.right = new Node(3);
    		head.left.left = new Node(Integer.MIN_VALUE);
    		head.right.left = new Node(55555555);
    		head.right.right = new Node(66);
    		head.left.left.right = new Node(777);
    		printTree(head);
    
    		head = new Node(1);
    		head.left = new Node(2);
    		head.right = new Node(3);
    		head.left.left = new Node(4);
    		head.right.left = new Node(5);
    		head.right.right = new Node(6);
    		head.left.left.right = new Node(7);
    		printTree(head);
    
    		head = new Node(1);
    		head.left = new Node(1);
    		head.right = new Node(1);
    		head.left.left = new Node(1);
    		head.right.left = new Node(1);
    		head.right.right = new Node(1);
    		head.left.left.right = new Node(1);
    		printTree(head);
    	}
    }
    

    如何完成二叉树的宽度优先遍历(常见题目:求一棵二叉树的宽度)

    import java.util.HashMap;
    import java.util.LinkedList;
    
    public class TreeMaxWidth {
    
    	public static class Node {
    		public int value;
    		public Node left;
    		public Node right;
    
    		public Node(int data) {
    			this.value = data;
    		}
    	}  
    
    	public static int getMaxWidth2(Node head) {
    		if (head == null) {
    			return 0;
    		}
    		int maxWidth = 0;
    		int curWidth = 0;
    		int curLevel = 0;
    		HashMap<Node, Integer> levelMap = new HashMap<>();
    		levelMap.put(head, 1);
    		LinkedList<Node> queue = new LinkedList<>();
    		queue.add(head);
    		Node node = null;
    		Node left = null;
    		Node right = null;
    		while (!queue.isEmpty()) {
    			node = queue.poll();
    			left = node.left;
    			right = node.right;
    			if (left != null) {
    				levelMap.put(left, levelMap.get(node) + 1);
    				queue.add(left);
    			}
    			if (right != null) {
    				levelMap.put(right, levelMap.get(node) + 1);
    				queue.add(right);
    			}
    			if (levelMap.get(node) > curLevel) {
    				curWidth = 0;
    				curLevel = levelMap.get(node);
    			} else {
    				curWidth++;
    			}
    			maxWidth = Math.max(maxWidth, curWidth);
    		}
    		return maxWidth;
    	}
    }
    

    C++二叉树的实现

    二叉树节点

    BinNode模板类

    #define BinNodePosi(T) BinNode<T>* //节点位置
    #define stature(p) ((p) ? (p)->height : -1) //节点高度(与“空树高度为-1”的约定相统一)
    typedef enum { RB_RED, RB_BLACK} RBColor; //节点颜色
    
    template <typename T> struct BinNode { //二叉树节点模板类
    // 成员(为简化描述起见统一开放,读者可根据需要进一步封装)
       T data; //数值
       BinNodePosi(T) parent; BinNodePosi(T) lc; BinNodePosi(T) rc; //父节点及左、右孩子
       int height; //高度(通用)
       int npl; //Null Path Length(左式堆,也可直接用height代替)
       RBColor color; //颜色(红黑树)
    // 构造函数
       BinNode() :
          parent ( NULL ), lc ( NULL ), rc ( NULL ), height ( 0 ), npl ( 1 ), color ( RB_RED ) { }
       BinNode ( T e, BinNodePosi(T) p = NULL, BinNodePosi(T) lc = NULL, BinNodePosi(T) rc = NULL,
                 int h = 0, int l = 1, RBColor c = RB_RED ) :
          data ( e ), parent ( p ), lc ( lc ), rc ( rc ), height ( h ), npl ( l ), color ( c ) { }
    // 操作接口
       int size(); //统计当前节点后代总数,亦即以其为根的子树的规模
       BinNodePosi(T) insertAsLC ( T const& ); //作为当前节点的左孩子插入新节点
       BinNodePosi(T) insertAsRC ( T const& ); //作为当前节点的右孩子插入新节点
       BinNodePosi(T) succ(); //取当前节点的直接后继
       template <typename VST> void travLevel ( VST& ); //子树层次遍历
       template <typename VST> void travPre ( VST& ); //子树先序遍历
       template <typename VST> void travIn ( VST& ); //子树中序遍历
       template <typename VST> void travPost ( VST& ); //子树后序遍历
    // 比较器、判等器(各列其一,其余自行补充)
       bool operator< ( BinNode const& bn ) { return data < bn.data; } //小于
       bool operator== ( BinNode const& bn ) { return data == bn.data; } //等于
    };
    

    快捷方式

    /************************************************************************************
     * BinNode状态与性质的判断
     ***********************************************************************************/
    #define IsRoot(x) ( ! ( (x).parent ) )
    #define IsLChild(x) ( ! IsRoot(x) && ( & (x) == (x).parent->lc ) )
    #define IsRChild(x) ( ! IsRoot(x) && ( & (x) == (x).parent->rc ) )
    #define HasParent(x) ( ! IsRoot(x) )
    #define HasLChild(x) ( (x).lc )
    #define HasRChild(x) ( (x).rc )
    #define HasChild(x) ( HasLChild(x) || HasRChild(x) ) //至少拥有一个孩子
    #define HasBothChild(x) ( HasLChild(x) && HasRChild(x) ) //同时拥有两个孩子
    #define IsLeaf(x) ( ! HasChild(x) )
    
    /************************************************************************************
     * 与BinNode具有特定关系的节点及指针
     ***********************************************************************************/
    #define sibling(p) /*兄弟*/ 
       ( IsLChild( * (p) ) ? (p)->parent->rc : (p)->parent->lc )
    
    #define uncle(x) /*叔叔*/ 
       ( IsLChild( * ( (x)->parent ) ) ? (x)->parent->parent->rc : (x)->parent->parent->lc )
    
    #define FromParentTo(x) /*来自父亲的引用*/ 
       ( IsRoot(x) ? _root : ( IsLChild(x) ? (x).parent->lc : (x).parent->rc ) )
    

    二叉树节点操作接口

    插入孩子节点

    template <typename T> BinNodePosi(T) BinNode<T>::insertAsLC ( T const& e )
    { return lc = new BinNode ( e, this ); } //将e作为当前节点的左孩子插入二叉树
    
    template <typename T> BinNodePosi(T) BinNode<T>::insertAsRC ( T const& e )
    { return rc = new BinNode ( e, this ); } //将e作为当前节点的右孩子插入二叉树
    

    遍历

    template <typename T> template <typename VST> //元素类型、操作器
    //二叉树中序遍历算法统一入口
    void BinNode<T>::travIn ( VST& visit ) { 
       switch ( rand() % 5 ) { //此处暂随机选择以做测试,共五种选择
          case 1: travIn_I1 ( this, visit ); break; //迭代版#1
          case 2: travIn_I2 ( this, visit ); break; //迭代版#2
          case 3: travIn_I3 ( this, visit ); break; //迭代版#3
          case 4: travIn_I4 ( this, visit ); break; //迭代版#4
          default: travIn_R ( this, visit ); break; //递归版
       }
    }
    

    二叉树

    BinTree模板类

    #include "BinNode.h" //引入二叉树节点类
    template <typename T> class BinTree { //二叉树模板类
    protected:
       int _size; BinNodePosi(T) _root; //规模、根节点
       virtual int updateHeight ( BinNodePosi(T) x ); //更新节点x的高度
       void updateHeightAbove ( BinNodePosi(T) x ); //更新节点x及其祖先的高度
    public:
       BinTree() : _size ( 0 ), _root ( NULL ) { } //构造函数
       ~BinTree() { if ( 0 < _size ) remove ( _root ); } //析构函数
       int size() const { return _size; } //规模
       bool empty() const { return !_root; } //判空
       BinNodePosi(T) root() const { return _root; } //树根
       BinNodePosi(T) insertAsRoot ( T const& e ); //插入根节点
       //e作为x的左孩子(原无)插入
       BinNodePosi(T) insertAsLC ( BinNodePosi(T) x, T const& e );
       //e作为x的右孩子(原无)插入
       BinNodePosi(T) insertAsRC ( BinNodePosi(T) x, T const& e ); 
       BinNodePosi(T) attachAsLC ( BinNodePosi(T) x, BinTree<T>* &T ); //T作为x左子树接入
       BinNodePosi(T) attachAsRC ( BinNodePosi(T) x, BinTree<T>* &T ); //T作为x右子树接入
       int remove ( BinNodePosi(T) x ); //删除以位置x处节点为根的子树,返回该子树原先的规模
       BinTree<T>* secede ( BinNodePosi(T) x ); //将子树x从当前树中摘除,并将其转换为一棵独立子树
       template <typename VST> //操作器
       void travLevel ( VST& visit ) { if ( _root ) _root->travLevel ( visit ); } //层次遍历
       template <typename VST> //操作器
       void travPre ( VST& visit ) { if ( _root ) _root->travPre ( visit ); } //先序遍历
       template <typename VST> //操作器
       void travIn ( VST& visit ) { if ( _root ) _root->travIn ( visit ); } //中序遍历
       template <typename VST> //操作器
       void travPost ( VST& visit ) { if ( _root ) _root->travPost ( visit ); } //后序遍历
       bool operator< ( BinTree<T> const& t ) //比较器(其余自行补充)
       { return _root && t._root && lt ( _root, t._root ); }
       bool operator== ( BinTree<T> const& t ) //判等器
       { return _root && t._root && ( _root == t._root ); }
    }; //BinTree
    

    高度更新

    template <typename T> int BinTree<T>::updateHeight ( BinNodePosi(T) x ) //更新节点x高度
    //具体规则,因树而异
    { return x->height = 1 + max ( stature ( x->lc ), stature ( x->rc ) ); } 
    //更新高度
    template <typename T> void BinTree<T>::updateHeightAbove ( BinNodePosi(T) x ) 
    { while ( x ) { updateHeight ( x ); x = x->parent; } } //从x出发,覆盖历代祖先。可优化
    

    节点插入

    template <typename T> BinNodePosi(T) BinTree<T>::insertAsRoot ( T const& e )
    { _size = 1; return _root = new BinNode<T> ( e ); } //将e当作根节点插入空的二叉树
    
    template <typename T> BinNodePosi(T) BinTree<T>::insertAsRC ( BinNodePosi(T) x, T const& e )
    //e插入为x的右孩子
    { _size++; x->insertAsRC ( e ); updateHeightAbove ( x ); return x->rc; } 
    //insertAsLC()完全对称,在此省略
    

    子树接入

    template <typename T> //二叉树子树接入算法:将S当作节点x的左子树接入,S本身置空
    BinNodePosi(T) BinTree<T>::attachAsLC ( BinNodePosi(T) x, BinTree<T>* &S ) { 
       //x->lc == NULL
       if ( x->lc = S->_root ) x->lc->parent = x; //接入
       _size += S->_size; updateHeightAbove ( x ); //更新全树规模与x所有祖先的高度
       //释放原树,返回接入位置
       S->_root = NULL; S->_size = 0; release ( S ); S = NULL; return x; 
    }
    
    template <typename T> //二叉树子树接入算法:将S当作节点x的右子树接入,S本身置空
    BinNodePosi(T) BinTree<T>::attachAsRC ( BinNodePosi(T) x, BinTree<T>* &S ) { //x->rc == NULL
       if ( x->rc = S->_root ) x->rc->parent = x; //接入
       _size += S->_size; updateHeightAbove ( x ); //更新全树规模与x所有祖先的高度
       //释放原树,返回接入位置
       S->_root = NULL; S->_size = 0; release ( S ); S = NULL; return x; 
    }
    

    子树删除

    template <typename T> //二叉树子树分离算法:将子树x从当前树中摘除,将其封装为一棵独立子树返回
    BinTree<T>* BinTree<T>::secede ( BinNodePosi(T) x ) { //assert: x为二叉树中的合法位置
       FromParentTo ( *x ) = NULL; //切断来自父节点的指针
       updateHeightAbove ( x->parent ); //更新原树中所有祖先的高度
       BinTree<T>* S = new BinTree<T>; S->_root = x; x->parent = NULL; //新树以x为根
       S->_size = x->size(); _size -= S->_size; return S; //更新规模,返回分离出来的子树
    }
    

    遍历

    先序遍历

    template <typename T, typename VST> //元素类型、操作器
    void travPre_R ( BinNodePosi(T) x, VST& visit ) { //二叉树先序遍历算法(递归版)
       if ( !x ) return;
       visit ( x->data );
       travPre_R ( x->lc, visit );
       travPre_R ( x->rc, visit );
    }
    
    

    后序遍历

    template <typename T, typename VST> //元素类型、操作器
    void travPost_R ( BinNodePosi(T) x, VST& visit ) { //二叉树后序遍历算法(递归版)
       if ( !x ) return;
       travPost_R ( x->lc, visit );
       travPost_R ( x->rc, visit );
       visit ( x->data );
    }
    

    中序遍历

    template <typename T, typename VST> //元素类型、操作器
    void travIn_R ( BinNodePosi(T) x, VST& visit ) { //二叉树中序遍历算法(递归版)
       if ( !x ) return;
       travIn_R ( x->lc, visit );
       visit ( x->data );
       travIn_R ( x->rc, visit );
    }
    
    如何判断一颗二叉树是完全二叉树?

    每一层都是满的,最后一层由左到右

    • 有右无左
    • 不违规条件1,如果遇到第一个左右子不全,后续都是叶节点
    import java.util.LinkedList;
    
    public class IsCBT {
    
    	public static class Node {
    		public int value;
    		public Node left;
    		public Node right;
    
    		public Node(int data) {
    			this.value = data;
    		}
    	}
    
    	public static boolean isCBT(Node head) {
    		if (head == null) {
    			return true;
    		}
    		LinkedList<Node> queue = new LinkedList<>();
    		boolean leaf = false;
    		Node l = null;
    		Node r = null;
    		queue.add(head);
    		while (!queue.isEmpty()) {
    			head = queue.poll();
    			l = head.left;
    			r = head.right;
    			if ((leaf && (l != null || r != null)) || (l == null && r != null)) {
    				return false;
    			}
    			if (l != null) {
    				queue.add(l);
    			}
    			if (r != null) {
    				queue.add(r);
    			} else {
    				leaf = true;
    			}
    		}
    		return true;
    	}
    }
    

    二叉树的相关概念及其实现判断

    树型DP

    如何判断一颗二叉树是否是搜索二叉树?

    左子树比右子树小,中序遍历判断是否升序

    import java.util.LinkedList;
    
    public class IsBST {
    
    	public static class Node {
    		public int value;
    		public Node left;
    		public Node right;
    
    		public Node(int data) {
    			this.value = data;
    		}
    	}
    
    	public static boolean isBST(Node head) {
    		if (head == null) {
    			return true;
    		}
    		LinkedList<Node> inOrderList = new LinkedList<>();
    		process(head, inOrderList);
    		int pre = Integer.MIN_VALUE;
    		for (Node cur : inOrderList) {
    			if (pre >= cur.value) {
    				return false;
    			}
    			pre = cur.value;
    		}
    		return true;
    	}
    
    	public static void process(Node node, LinkedList<Node> inOrderList) {
    		if (node == null) {
    			return;
    		}
    		process(node.left, inOrderList);
    		inOrderList.add(node);
    		process(node.right, inOrderList);
    	}
    }
    

    递归套路,左右树都是搜索树

    左max<x,右min>x

    	public static class ReturnData{
    		public boolean isBST;
    		public int min;
    		public int max;
    		public ReturnData(boolean is, int mi, int ma){
    			isBST = is;
    			min = mi;
    			max = ma;
    		}
    	}
    
    	public static ReturnData process(Node x){
    		if(x==null){
    			return null;
    		}
    		ReturnData leftData = process(x.left);
    		ReturnData rightData = process(x.right);
    		int min = x.value;
    		int max = x.value;
    		if(leftData!=null){
    			min = Math.min(min, leftData.min);
    			max = Math.max(max, leftData.max);
    		}
    		if(rightData!=null){
    			min = Math.min(min, rightData.min);
    			max = Math.max(max, rightData.max);
    		}
    		boolean isBST = true;
    		if(leftData!=null && (!leftData.isBST || leftData.max >= x.value)){
    			isBST = false;
    		}
    		if(rightData!=null && (!rightData.isBST || x.value >= rightData.min )){
    			isBST = false;
    		}
    		return new ReturnData(isBST, min, max);
    	}
    
    如何判断一颗二叉树是否是满二叉树?

    返回 整棵树的高度 和 整棵树的节点个数

    	public static boolean isF(Node head){
    		if(head == null){
    			return true;
    		}
    		Info data = f(head)
    	}
    	public static class Info{
    		public int height;
    		public int nodes;
    
    		public Info(int h, int n){
    			height = h;
    			nodes = n;
    		}
    	}
    
    	public static Info f(Node){
    		if(x==null){
    			return new Info(0,0);
    		}
    		Info leftData = f(x.left);
    		Info rightData = f(x.right);
    		int height = Math.max(leftData.height,rightData.height)+1;
    		int nodes = leftData.nodes + rightData.nodes + 1;
    		return new Info(height, nodes);
    	}
    
    如何判断一颗二叉树是否是平衡二叉树?(二叉树题目套路)

    左右树是平衡树

    |左高-右高|=<1

    public class IsBalancedTree {
    
    	public static class Node {
    		public int value;
    		public Node left;
    		public Node right;
    
    		public Node(int data) {
    			this.value = data;
    		}
    	}
    
    	public static boolean isBalanced(Node head) {
    		return process(head).isBalanced;
    	}
    
    	public static class ReturnType {
    		public boolean isBalanced;
    		public int height;
    
    		public ReturnType(boolean isB, int hei) {
    			isBalanced = isB;
    			height = hei;
    		}
    	}
    
    	public static ReturnType process(Node x) {
    		if (x == null) {
    			return new ReturnType(true, 0);
    		}
    		ReturnType leftData = process(x.left);
    		ReturnType rightData = process(x.right);
    		int height = Math.max(leftData.height, rightData.height);
    		boolean isBalanced = leftData.isBalanced && rightData.isBalanced
    				&& Math.abs(leftData.height - rightData.height) < 2;
    		return new ReturnType(isBalanced, height);
    	}
    }
    

    最低公共祖先节点

    给定两个二叉树的节点node 1和node2,找到他们的最低公共祖先节点

    	// o1和o2一定属于head为头的树
    	// 返回o1和o2的最低公共祖先
    	public static Node lca(Node head, Node o1. o2){
    		HashMap<Node, Node> fatherMap = new HashMap<>();
    		fatherMap.put(head,head);
    		process(head, fatherMap);
    		HashSet<Node> set1 = new HashSet<>();
    
    		Node cur = o1l;
    		while(cur != fatherMap.get(cur)){
    			set1.add(cur);
    			cur = fatherMap.get(cur);
    		}
    		set1.add(head);
    
    		//while ()  o2
    
    	}
    	public static void process(Node head, HashMap<Node, Node> fatherMap){
    		if(head == null){
    			return;
    		}
    		fatherMap.put(head.left,head);
    		fatherMap.put(head.right,head);
    		process(head.left,fatherMap);
    		process(head.right,fatherMap);
    	}
    

    方法二

    • o1是o2的公共祖先或o2是o1的公共祖先
    • o1与o2互不为公共祖先,往上才能找到
    public static Node lowestAncestor(Node head, Node o1, Node o2){
    	if (head == null || head == o1 || head == o2) {
    		return head;
    	}
    	Node left = lowestAncestor(head.left, o1, o2);
    	Node right = lowestAncestor(head.right, o1, o2);
    	if (left != null && right != null) {
    		return head;
    	}
        //左右两棵树,并不都有返回值
    	return left != null ? left : right;
    }
    

    在二叉树中找到一个节点的后继节点

    【题目】现在有一种新的二叉树节点类型如下:

    public class Node { 
    		public int value;
    		public Node left;
    		public Node right; public Node parent;
    		public Node (int val) { 
    				value = val;
    		}
    }
    

    该结构比普通二叉树节点结构多了一个指向父节点的parent指针。

    假设有一棵Node类型的节点组成的二叉树,树中每个节点的parent指针都正确地指向自己的父节点,头节 点的parent指向nul l。

    只给一个在二叉树中的某个节点node,请实现返回node的后继节点的函数。 在二叉树的中序遍历的序列中,node的下一个节点叫作node的后继节点。

    后继节点,中序遍历的下一个

    • X有右树的时候
    • X无右树
    public static Node getSuccessorNode(Node node) {
       if (node == null) {
          return node;
       }
       if (node.right != null) {
          return getLeftMost(node.right);
       } else {  //无右子树
          Node parent = node.parent;
          while (parent != null && parent.left != node) {  
             //当前节点是其父亲节点右孩子
             node = parent;
             parent = node.parent;
          }
          return parent;
       }
    }
    

    二叉树的序列化和反序列化

    就是内存里的一棵树如何变成字符串形式,又如何从字符串形式变成内存里的树

    如何判断一颗二叉树是不是另一棵二叉树的子树?

    	public static String serialByPre(Node head) {
    		if (head == null) {
    			return "#!";
    		}
    		String res = head.value + "!";
    		res += serialByPre(head.left);
    		res += serialByPre(head.right);
    		return res;
    	}
    
    	public static Node reconByPreString(String preStr) {
    		String[] values = preStr.split("!");
    		Queue<String> queue = new LinkedList<String>();
    		for (int i = 0; i != values.length; i++) {
    			queue.offer(values[i]);
    		}
    		return reconPreOrder(queue);
    	}
    
    	public static Node reconPreOrder(Queue<String> queue) {
    		String value = queue.poll();
    		if (value.equals("#")) {
    			return null;
    		}
    		Node head = new Node(Integer.valueOf(value));
    		head.left = reconPreOrder(queue);
    		head.right = reconPreOrder(queue);
    		return head;
    	}
    

    折纸问题

    请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开。

    此时折痕是凹下去的,即折痕突起的方向指向纸条的背面。

    如果从纸条的下边向上方连续对折2次,压出折痕后展开,此时有三条折痕,从 上到下依次是下折痕、下折痕和上折痕。

    给定一个输入参数N,代表纸条都从下边向上方连续对折N次。

    请从上到下打印所有折痕的方向。

    例如:N=1 时,打印:down N=2时,打印:down down up

    public class Code10_PaperFolding {
    
    	public static void printAllFolds(int N) {
    		printProcess(1, N, true);
    	}
    
    	public static void printProcess(int i, int N, boolean down{
    		if (i > N) {
    			return;
    		}
    		printProcess(i + 1, N, true);
    		System.out.println(down ? "down " : "up ");
    		printProcess(i + 1, N, false);
    	}
    
    	public static void main(String[] args) {
    		int N = 1;
    		printAllFolds(N);
    	}
    }
    
  • 相关阅读:
    云南大学2020年数学分析考研试题参考解答
    北京科技大学2020年高等代数考研试题参考解答
    北京科技大学2020年数学分析考研试题参考解答
    [免费解答]北京工业大学2020年高等代数考研试题参考解答
    [免费解答]华中师范大学2019年数学分析考研试题参考解答
    [免费解答]中国矿业大学2020年高等代数考研试题参考解答[见跟锦数学微信公众号]
    [免费解答]湖南大学2020年数学分析考研试题参考解答[见跟锦数学微信公众号]
    [免费解答]南开大学2020年高等代数考研试题参考解答[见跟锦数学微信公众号]
    [免费解答]安徽大学2020年数学分析考研试题参考解答[见跟锦数学微信公众号]
    [免费解答]上海大学2020年高等代数考研试题参考解答[见跟锦数学微信公众号]
  • 原文地址:https://www.cnblogs.com/wwj99/p/12205284.html
Copyright © 2011-2022 走看看