最常见的程序员面试题(7)二叉树转链表

二叉树通过遍历可以用于转化成一个链表(插入构建链表)。但是如果没有而外的链表呢? 这就用到"线索化二叉树",也就是一个二叉树(可以是排序二叉树)在座遍历(例如中序)的时候,去更新每个节点的"前驱"和"后继"的节点关系,得到一个二叉链表。然后从最左节点开始,遍历所有的"后继"节点,就得到一个二叉链表的所有数据。分别用C++和Java来实现。

(1)第一种情况,也是简单的情况,允许以侵入的方式把二叉树变成双向链表。这需要做几件事情。对于任意一个节点来说,如果左子树存在,那么左子树变成2叉链表以后,左子树的"最后的指针"指向当前节点。如果右子树存在,那么当前节点的新的右节点(也就是2叉链表的next),就是右节点的最左元素。函数返回右子树的"最后指针"。Java程序如下:

  1. public class my{  
  2.     public static void main(String[] args){  
  3.         class node{  
  4.             node left=null;  
  5.             node right=null;  
  6.             int data=0;  
  7.             node(int d){data=d;}  
  8.             void appendLeft(node n){  
  9.                 if(left==null)left=n;  
  10.                 else left.append(n);  
  11.             }  
  12.             void appendRight(node n){  
  13.                 if(right==null)right=n;  
  14.                 else right.append(n);  
  15.             }  
  16.             void append(node n){  
  17.                 if(data>n.data)appendLeft(n);  
  18.                 else appendRight(n);  
  19.             }  
  20.             void print(){  
  21.                 if(left!=null)left.print();  
  22.                 System.out.print(","+data);  
  23.                 if(right!=null)right.print();  
  24.             }  
  25.             node helper(){//返回最后的节点   
  26.                 if(left!=null){  
  27.                     node leftPtr=left.helper();  
  28.                     leftPtr.right=this;  
  29.                 }  
  30.                 node ret=this;  
  31.                 if(right!=null){  
  32.                     ret=right.helper();  
  33.                     node rightPtr=right.LeftestNode();  
  34.                     right=rightPtr;  
  35.                 }  
  36.                 return ret;//叶子节点总是返回自身   
  37.             }  
  38.             node LeftestNode(){//叶子节点总是返回自身   
  39.                 node p=this;  
  40.                 while(p.left!=null){  
  41.                     p=p.left;  
  42.                 }  
  43.                 return p;  
  44.             }  
  45.         }  
  46.         class tree{  
  47.             node root=null;  
  48.             tree(int d){root=new node(d);}  
  49.             void append(int d){root.append(new node(d));}  
  50.             void display(){root.print();}  
  51.             void Tree2List(){  
  52.                 node leftest=root.LeftestNode();  
  53.                 root.helper();  
  54.                 while(leftest!=null){  
  55.                     System.out.print(","+leftest.data);  
  56.                     leftest=leftest.right;  
  57.                 }  
  58.             }  
  59.         }  
  60.         tree t=new tree(5);  
  61.         t.append(2);  
  62.         t.append(7);  
  63.         t.append(1);  
  64.         t.append(6);  
  65.         t.append(8);  
  66.         t.append(3);  
  67.         t.display();  
  68.         System.out.println("\n===========");  
  69.         t.Tree2List();  
  70.     }  
  71. }  
public class my{
	public static void main(String[] args){
		class node{
			node left=null;
			node right=null;
			int data=0;
			node(int d){data=d;}
			void appendLeft(node n){
				if(left==null)left=n;
				else left.append(n);
			}
			void appendRight(node n){
				if(right==null)right=n;
				else right.append(n);
			}
			void append(node n){
				if(data>n.data)appendLeft(n);
				else appendRight(n);
			}
			void print(){
				if(left!=null)left.print();
				System.out.print(","+data);
				if(right!=null)right.print();
			}
			node helper(){//返回最后的节点
				if(left!=null){
					node leftPtr=left.helper();
					leftPtr.right=this;
				}
				node ret=this;
				if(right!=null){
					ret=right.helper();
					node rightPtr=right.LeftestNode();
					right=rightPtr;
				}
				return ret;//叶子节点总是返回自身
			}
			node LeftestNode(){//叶子节点总是返回自身
				node p=this;
				while(p.left!=null){
					p=p.left;
				}
				return p;
			}
		}
		class tree{
			node root=null;
			tree(int d){root=new node(d);}
			void append(int d){root.append(new node(d));}
			void display(){root.print();}
			void Tree2List(){
				node leftest=root.LeftestNode();
				root.helper();
				while(leftest!=null){
					System.out.print(","+leftest.data);
					leftest=leftest.right;
				}
			}
		}
		tree t=new tree(5);
		t.append(2);
		t.append(7);
		t.append(1);
		t.append(6);
		t.append(8);
		t.append(3);
		t.display();
		System.out.println("\n===========");
		t.Tree2List();
	}
}

(2) 如果不允许修改2叉树本身,那么就要借助于线索化2叉树,这个会复杂一点,但是能够做到同样的效果。

分别用C++和Java实现

  1. #include<functional>   
  2. using namespace std;  
  3. template<class Comp>  
  4. class node{  
  5.     size_t data;  
  6.     node* pLeft;  
  7.     node* pRight;  
  8.     bool lTag;//true表示node*pLeft/pRight是线索,false表示指针   
  9.     bool rTag;  
  10. public:  
  11.     node( size_t d ):  
  12.         data(d),  
  13.         pLeft(nullptr),  
  14.         pRight(nullptr),  
  15.         lTag(true),  
  16.         rTag(true)  
  17.     {}  
  18.     void append( node* p ){  
  19.         if( Comp()( p->data, data ) ){  
  20.             appendLeft( p );  
  21.         }else{  
  22.             appendRight( p );  
  23.         }  
  24.     }  
  25.     void appendLeft( node* p ){  
  26.         if( pLeft == nullptr ){  
  27.             pLeft = p;  
  28.         }else{  
  29.             pLeft->append( p );  
  30.         }  
  31.         lTag=false;  
  32.     }  
  33.     void appendRight( node* p ){  
  34.         if( pRight == nullptr ){  
  35.             pRight = p;  
  36.         }else{  
  37.             pRight->append( p );  
  38.         }  
  39.         rTag=false;  
  40.     }  
  41.     ~node(){  
  42.         if(pLeft && (lTag==false))delete pLeft;  
  43.         if(pRight&& (rTag==false))delete pRight;  
  44.     }  
  45.     void printTree(){//中序遍历打印   
  46.         if(pLeft)pLeft->printTree();  
  47.         printf("%d,",data);  
  48.         if(pRight)pRight->printTree();  
  49.     }  
  50.     void ToThreadedBinarytree(){//中序线索2叉树   
  51.         static node* pre=nullptr;  
  52.         if(pLeft){  
  53.             pLeft->ToThreadedBinarytree();  
  54.         }else{  
  55.             pLeft=pre;  
  56.             lTag=true;  
  57.         }  
  58.         if(pre){  
  59.             if(pre->pRight==nullptr){  
  60.                 pre->pRight=this;  
  61.                 pre->rTag=true;  
  62.             }           
  63.         }  
  64.         pre=this;  
  65.         if(pRight){  
  66.             pRight->ToThreadedBinarytree();  
  67.         }  
  68.     }  
  69.     void printList(){  
  70.         node*p=this;  
  71.         while(p->pLeft && (p->lTag==false)){  
  72.             p=p->pLeft;  
  73.         }//找到当前树的最左节点   
  74.         p->printThreaded();  
  75.     }  
  76.     void printThreaded(){//寻找后继结点并打印   
  77.         printf("%d,",data);  
  78.         if(rTag){  
  79.             if(pRight)pRight->printThreaded();  
  80.         }else{  
  81.             if(pRight)pRight->printList();  
  82.         }  
  83.     }  
  84. };  
  85. template<class T>  
  86. struct sortedTree{  
  87.     node<T>* pRoot;  
  88.     sortedTree():pRoot(nullptr){}  
  89.     ~sortedTree(){if(pRoot)delete pRoot;}  
  90.     void append( size_t n ){  
  91.         node<T>* p=new node<T>(n);  
  92.         if( pRoot == nullptr ){  
  93.             pRoot = p;  
  94.         }else{  
  95.             pRoot->append( p );  
  96.         }  
  97.     }  
  98.     void printTree(){  
  99.         if(pRoot)pRoot->printTree();  
  100.     }  
  101.     void convertList(){  
  102.         if(pRoot){  
  103.             pRoot->ToThreadedBinarytree();  
  104.             printf("\n");  
  105.             pRoot->printList();  
  106.         }  
  107.     }  
  108. };  
  109. int main(int argc, charconst argv[]){  
  110.     sortedTree< less<size_t> > tree;  
  111.     tree.append( 3 );  
  112.     tree.append( 7 );  
  113.     tree.append( 4 );  
  114.     tree.append( 2 );  
  115.     tree.append( 5 );  
  116.     tree.append( 1 );  
  117.     tree.append( 6 );  
  118.     tree.printTree();  
  119.     printf("\n");  
  120.     tree.convertList();//打印线索化的二叉树   
  121.     printf("\n");  
  122.     return 0;  
  123. }  
#include<functional>
using namespace std;
template<class Comp>
class node{
    size_t data;
    node* pLeft;
    node* pRight;
    bool lTag;//true表示node*pLeft/pRight是线索,false表示指针
    bool rTag;
public:
    node( size_t d ):
        data(d),
        pLeft(nullptr),
        pRight(nullptr),
        lTag(true),
        rTag(true)
    {}
    void append( node* p ){
        if( Comp()( p->data, data ) ){
            appendLeft( p );
        }else{
            appendRight( p );
        }
    }
    void appendLeft( node* p ){
        if( pLeft == nullptr ){
            pLeft = p;
        }else{
            pLeft->append( p );
        }
        lTag=false;
    }
    void appendRight( node* p ){
        if( pRight == nullptr ){
            pRight = p;
        }else{
            pRight->append( p );
        }
        rTag=false;
    }
    ~node(){
        if(pLeft && (lTag==false))delete pLeft;
        if(pRight&& (rTag==false))delete pRight;
    }
    void printTree(){//中序遍历打印
        if(pLeft)pLeft->printTree();
        printf("%d,",data);
        if(pRight)pRight->printTree();
    }
    void ToThreadedBinarytree(){//中序线索2叉树
        static node* pre=nullptr;
        if(pLeft){
            pLeft->ToThreadedBinarytree();
        }else{
            pLeft=pre;
            lTag=true;
        }
        if(pre){
            if(pre->pRight==nullptr){
                pre->pRight=this;
                pre->rTag=true;
            }         
        }
        pre=this;
        if(pRight){
            pRight->ToThreadedBinarytree();
        }
    }
    void printList(){
        node*p=this;
        while(p->pLeft && (p->lTag==false)){
            p=p->pLeft;
        }//找到当前树的最左节点
        p->printThreaded();
    }
    void printThreaded(){//寻找后继结点并打印
        printf("%d,",data);
        if(rTag){
            if(pRight)pRight->printThreaded();
        }else{
            if(pRight)pRight->printList();
        }
    }
};
template<class T>
struct sortedTree{
    node<T>* pRoot;
    sortedTree():pRoot(nullptr){}
    ~sortedTree(){if(pRoot)delete pRoot;}
    void append( size_t n ){
        node<T>* p=new node<T>(n);
        if( pRoot == nullptr ){
            pRoot = p;
        }else{
            pRoot->append( p );
        }
    }
    void printTree(){
        if(pRoot)pRoot->printTree();
    }
    void convertList(){
        if(pRoot){
            pRoot->ToThreadedBinarytree();
            printf("\n");
            pRoot->printList();
        }
    }
};
int main(int argc, char* const argv[]){
    sortedTree< less<size_t> > tree;
    tree.append( 3 );
    tree.append( 7 );
    tree.append( 4 );
    tree.append( 2 );
    tree.append( 5 );
    tree.append( 1 );
    tree.append( 6 );
    tree.printTree();
    printf("\n");
    tree.convertList();//打印线索化的二叉树
    printf("\n");
    return 0;
}
  1. public class TreeToList{  
  2.     static class node{  
  3.         node pLeft;  
  4.         node pRight;  
  5.         boolean lTag;//true代表是线索   
  6.         boolean rTag;  
  7.         int data;  
  8.         node(int d){  
  9.             data=d;  
  10.             pLeft=null;  
  11.             pRight=null;  
  12.             lTag=false;  
  13.             rTag=false;  
  14.         }  
  15.         void append(node n){  
  16.             if(data>n.data){  
  17.                 appendLeft(n);  
  18.             }  
  19.             else{  
  20.                 appendRight(n);  
  21.             }  
  22.         }  
  23.         void appendLeft(node n){  
  24.             if(pLeft==null){  
  25.                 pLeft=n;  
  26.             }  
  27.             else{  
  28.                 pLeft.append(n);  
  29.             }  
  30.             lTag=false;  
  31.         }  
  32.         void appendRight(node n){  
  33.             if(pRight==null){  
  34.                 pRight=n;  
  35.             }  
  36.             else{  
  37.                 pRight.append(n);  
  38.             }  
  39.             rTag=false;  
  40.         }  
  41.         void printNode(){  
  42.             if(pLeft !=null){  
  43.                 pLeft.printNode();  
  44.             }  
  45.             System.out.println(","+data);  
  46.             if(pRight!=null){  
  47.                 pRight.printNode();  
  48.             }  
  49.         }  
  50.         static node pre;  
  51.         static{  
  52.             pre=null;  
  53.         }  
  54.         void ToThreadedBinaryTree(){  
  55.             if(pLeft!=null){  
  56.                 pLeft.ToThreadedBinaryTree();  
  57.             }else{  
  58.                 pLeft=pre;  
  59.                 lTag=true;  
  60.             }  
  61.             if(pre!=null){  
  62.                 if(pre.pRight==null){  
  63.                     pre.pRight=this;  
  64.                     pre.rTag=true;  
  65.                 }  
  66.             }  
  67.             pre=this;  
  68.             if(pRight!=null){  
  69.                 pRight.ToThreadedBinaryTree();  
  70.             }  
  71.         }  
  72.         void printList(){  
  73.             node p=this;  
  74.             while(p.pLeft!=null && p.lTag==false){  
  75.                 p=p.pLeft;  
  76.             }//找到当前树的最左节点   
  77.             p.printThreaded();  
  78.         }  
  79.         void printThreaded(){  
  80.             System.out.println(","+data);  
  81.             if(rTag){  
  82.                 if(pRight!=null){  
  83.                     pRight.printThreaded();  
  84.                 }  
  85.             }else{  
  86.                 if(pRight!=null){  
  87.                     pRight.printList();  
  88.                 }  
  89.             }  
  90.         }  
  91.     }//end class node   
  92.     static class BTree{  
  93.         node pRoot;  
  94.         void append(node n){  
  95.             if(pRoot==null){  
  96.                 pRoot=n;  
  97.             }  
  98.             else{  
  99.                 pRoot.append(n);  
  100.             }  
  101.         }  
  102.         void printTree(){  
  103.             if(pRoot!=null){  
  104.                 pRoot.printNode();  
  105.             }  
  106.         }  
  107.         void convertList(){  
  108.             if(pRoot!=null){  
  109.                 pRoot.ToThreadedBinaryTree();  
  110.                 pRoot.printList();  
  111.             }  
  112.         }  
  113.     }//end class BTree   
  114.   
  115.     public static void main(String[] args) {  
  116.         BTree t=new BTree();  
  117.         t.append(new node(3));  
  118.         t.append(new node(7));  
  119.         t.append(new node(4));  
  120.         t.append(new node(2));  
  121.         t.append(new node(5));  
  122.         t.append(new node(1));  
  123.         t.append(new node(6));  
  124.         t.printTree();  
  125.         System.out.println("========");  
  126.         t.convertList();  
  127.     }  
  128. }  
public class TreeToList{
	static class node{
		node pLeft;
		node pRight;
		boolean lTag;//true代表是线索
		boolean rTag;
		int data;
		node(int d){
			data=d;
			pLeft=null;
			pRight=null;
			lTag=false;
			rTag=false;
		}
		void append(node n){
			if(data>n.data){
				appendLeft(n);
			}
			else{
				appendRight(n);
			}
		}
		void appendLeft(node n){
			if(pLeft==null){
				pLeft=n;
			}
			else{
				pLeft.append(n);
			}
			lTag=false;
		}
		void appendRight(node n){
			if(pRight==null){
				pRight=n;
			}
			else{
				pRight.append(n);
			}
			rTag=false;
		}
		void printNode(){
			if(pLeft !=null){
				pLeft.printNode();
			}
			System.out.println(","+data);
			if(pRight!=null){
				pRight.printNode();
			}
		}
		static node pre;
		static{
			pre=null;
		}
		void ToThreadedBinaryTree(){
			if(pLeft!=null){
				pLeft.ToThreadedBinaryTree();
			}else{
				pLeft=pre;
				lTag=true;
			}
			if(pre!=null){
				if(pre.pRight==null){
					pre.pRight=this;
					pre.rTag=true;
				}
			}
			pre=this;
			if(pRight!=null){
				pRight.ToThreadedBinaryTree();
			}
		}
		void printList(){
			node p=this;
			while(p.pLeft!=null && p.lTag==false){
				p=p.pLeft;
			}//找到当前树的最左节点
			p.printThreaded();
		}
		void printThreaded(){
			System.out.println(","+data);
			if(rTag){
				if(pRight!=null){
					pRight.printThreaded();
				}
			}else{
				if(pRight!=null){
					pRight.printList();
				}
			}
		}
	}//end class node
	static class BTree{
		node pRoot;
		void append(node n){
			if(pRoot==null){
				pRoot=n;
			}
			else{
				pRoot.append(n);
			}
		}
		void printTree(){
			if(pRoot!=null){
				pRoot.printNode();
			}
		}
		void convertList(){
			if(pRoot!=null){
				pRoot.ToThreadedBinaryTree();
				pRoot.printList();
			}
		}
	}//end class BTree

	public static void main(String[] args) {
		BTree t=new BTree();
		t.append(new node(3));
		t.append(new node(7));
		t.append(new node(4));
		t.append(new node(2));
		t.append(new node(5));
		t.append(new node(1));
		t.append(new node(6));
		t.printTree();
		System.out.println("========");
		t.convertList();
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值