线索二叉树
线索二叉树的定义为:一个二叉树通过如下的方法 “穿起来”:所有应该为空的右孩子指针指向该节点在中序序列中的后继,所有应该为空的左孩子指针指向该节点的中序序列的前驱。
那么在有 N 个节点的二叉树中共有 N+1 个空指针,这些空指针就叫做 “线索”。(提示:在一个有 N 个节点的二叉树中,每个节点有 2 个指针,所以一共有 2N 个指针,将这 N 个节点连接起来需要 N-1 条线,即使用了 N-1 个指针。所以剩下 2N-(N-1)=N+1 个空指针。)
基本操作的代码如下(以中序为例):
1 //线索二叉树的基本操作 2 3 //结点定义 4 struct Node{ 5 char data; 6 Node *lchild=NULL, *rchild=NULL; 7 //0 means it is not a thread, it points to its child 8 bool lflag=0, rflag=0; 9 }; 10 11 12 //中序线索化 13 void thread(node *&cur, node *&pre){ 14 if(cur==NULL){ 15 return; 16 } 17 //按中序,先处理左子树 18 thread(cur->lchild,pre); 19 20 //再处理当前结点 21 if(cur->lchild==NULL){ 22 cur->lflag=1; 23 cur->lchild=pre; 24 } 25 if(cur->rchild==NULL){ 26 cur->rflag=1; 27 } 28 //cur是pre的下一个结点 29 if(pre->rflag==1){ 30 pre->rchild=cur; 31 } 32 //处理完之后当前结点就成为了上一个结点 33 pre=cur; 34 35 //最后处理右子树 36 thread(cur->rchild,pre); 37 } 38 39 40 //将二叉树线索化并加上一个header串成一个环 41 void formLoop(Node *&root){ 42 //header可能需要设置为全局变量 43 //或者把整个写成一个class 44 Node *header=new Node; 45 header->lflag=1; 46 header->rflag=1; 47 48 Node *pre=header; 49 thread(root, pre); 50 51 //最后一个结点指回header 52 pre->rflag=1; 53 pre->rchild=header; 54 //header左指针指向树的最后一个结点 55 header->lchild=pre; 56 } 57 58 59 //获取目标结点的前驱 60 Node *precursor(Node *target){ 61 //check if it points to its precursor already 62 if(target->lflag==1){ 63 return target->lchild; 64 } 65 Node *temp=target->lchild; 66 //前驱是结点左子树的最右边的结点 67 while(temp->rflag!=1){ 68 temp=temp->rchild; 69 } 70 return temp; 71 } 72 73 74 //获取目标结点的后继 75 Node *successor(Node *target){ 76 if(target->rflag==1){ 77 return target->rchild; 78 } 79 Node *temp=target->rchild; 80 //后继是结点右子树的最左边的结点 81 while(temp->lflag!=1){ 82 temp=temp->lchild; 83 } 84 return temp; 85 } 86 87 88 //中序输出 89 void in_order_print(){ 90 //起点 91 Node *p=header->rchild; 92 while(p!=header){ 93 cout<<p->data<<" "; 94 p=successor(p); 95 } 96 cout<<endl; 97 }
参考:http://www.61mon.com/index.php/archives/190/