題目:輸入一棵二元尋找樹,將該二元尋找樹轉換成一個排序的雙向鏈表。要求不能建立任何新的結點,只調整指標的指向
比如二叉搜尋樹:
輸出應為: 3, 4, 5, 10, 11, 12, 13:
分析:
處理樹狀結構很容易想到遞迴,而二叉搜尋樹其實恰好是已經排序好的一個結構,而要把它變成連結,只需“中序遍曆”即可: 3,4,5,10,11,12,13,中序遍曆每訪問到一個節點的時候,需要將它的left指向指向它的前驅,它的區驅的right指標指向該節點。在中序遍曆的中間需要設定一個臨時前驅結點變數prior,每次訪問節點時,都要更新前驅。具體代碼如下:
#include<iostream>using namespace std;struct node//結點{int key;node* p;node* left;node* right;node(){}node(int k):key(k),p(NULL),left(NULL),right(NULL){}};struct TREE//樹{node* root;TREE():root(NULL){}};void tree_insert(TREE* T,node* z)//插入節點{node* y=NULL;node* x=T->root;//管理兩個指標,父指標y,y的子樹指標xwhile(x!=NULL)//一直向下遍曆到z應該插入的位置{y=x;if(x->key < z->key)x=x->right;else x=x->left;}z->p=y;//先將z的父指標p指向yif(y==NULL)//若樹為空白,樹根即為zT->root=z;else if(z->key < y->key)//否則分插入左邊還是右邊y->left=z;else y->right=z;}void tree_walk(node* x)//遞迴中序{static node* prior=NULL;//找x的前驅,比x小的最大值if(x!=NULL){tree_walk(x->left);if(prior){prior->right=x;//修改指標x->left=prior;}prior=x;//更新前驅tree_walk(x->right);}}node *head= NULL,*tail=NULL;//全域頭尾指標void find_head(node *cur){ node *ptr1=cur,*ptr2=cur; while(ptr1) { head = ptr1; ptr1 = ptr1->left; }while(ptr2) { tail = ptr2; ptr2 = ptr2->right; }}void double_link(node* x){tree_walk(x);find_head(x);}void main(){int A[]={10,6,14,4,8,12,16};int len=sizeof(A)/sizeof(A[0]);TREE* T=new TREE;node* z;for(int i=0;i<len;i++){z=new node(A[i]);tree_insert(T,z);}cout<<"Recursion"<<endl;double_link(T->root);while(head){cout<<head->key<<' ';head=head->right;}cout<<endl;while(tail){cout<<tail->key<<' ';tail=tail->left;}cout<<endl;}