2012-03-07 46 views
1

这是一个将二叉搜索树转换为排序双向链表的功能。想法是进行一次遍历并将访问节点放入一个大小为2的圆形数组中。然后调整左右指针以转换为双向链表。当前节点的右指针从不修改并稍后访问。问题出在哪里?将BST转换为排序的双向链表(调试)

void TreetoQueue(node* tnode) 
{static node* arr[2]={NULL,NULL}; 
    static int index=0; 
    if(tnode==NULL) return; 
    TreetoQueue(tnode->left); 
    arr[index]=tnode;  //current node 
    if(arr[1]!=NULL) 
     { if(index==0) 
     {arr[1]->right=arr[0]; //modify right pointer of inorder predecessor to point to current node 
     arr[0]->left=arr[1]; //modify current node's left pointer to point to inorder predecessor 
     } 

     if(index==1) 
     {arr[0]->right=arr[1]; 
     arr[1]->left=arr[0]; 
     } 
    cout<<"index-"<<index<<" "<<arr[0]->val<<" "<<arr[1]->val<<"\n"; 
    } 

    index=(index+1)%2; 
    TreetoQueue(tnode->right); 
    } 

      _______5______ 
     /   \ 
     ___3__    6__ 
    / \    \ 
    1  4    _9 
         /\ 
          7 10 


index-1 1 3 
index-0 4 3 
index-1 4 5 
index-0 6 5 
index-1 6 7 
index-0 9 7 
index-1 9 10 
node->left->left->right is NULL //Intended to be 3 
node->left->right->left is NULL//intended to be 3 
node->left->right->right is NULL//intended to be 5 

编辑:它可以作为intended.Only,我不得不改变根开始list.I用于其他功能做this.Could无我有一个额外的功能来实现这一点?

node* TreetoQueue2(node* root) 
     {node* head=root; 
     while(head->left!=NULL) 
     head=head->left; 
     TreetoQueue(root); 
     return head; 
     } 
+0

你说'如果(ARR [1]!= NULL)'。最初它被声明为NULL。之后我不会看到它改变。有什么我失踪? – noMAD 2012-03-07 22:42:19

+0

arr [index] = tnode和index =(index + 1)%2.arr [1]可以在输出中看到 – bl3e 2012-03-07 22:59:46

+1

您可以解释一下您奇怪的缩进方案吗? – 2012-03-07 23:03:48

回答

0

重申一下丹尼尔说,下面的测试代码的工作(使用g ++ - 4.7)预期:

#include <iostream> 

using namespace std; 

struct node { 
     node * left; 
     node * right; 
     int val; 
}; 

typedef node * node_ptr; 

void TreetoQueue(node* tnode) { 

     static node* arr[2]={NULL,NULL}; 

     static int index=0; 

     if(tnode==NULL) return; 

     TreetoQueue(tnode->left); 

     arr[index]=tnode;  //current node 

     if(arr[1]!=NULL) 
     { 
       if(index==0) 
       { 
         arr[1]->right=arr[0]; //modify right pointer of inorder predecessor to point to current node 
         arr[0]->left=arr[1]; //modify current node's left pointer to point to inorder predecessor 
       } 

       if(index==1) 
       { 
         arr[0]->right=arr[1]; 
         arr[1]->left=arr[0]; 
       } 
       cout<<"index-"<<index<<" "<<arr[0]->val<<" "<<arr[1]->val<<"\n"; 
     } 

     index=(index+1)%2; 
     TreetoQueue(tnode->right); 
} 

int main(int argc, char *argv[]){ 
     node_ptr np0 = new node(); 
     node_ptr np1 = new node(); 
     node_ptr np2 = new node(); 
     node_ptr np3 = new node(); 
     node_ptr np4 = new node(); 
     node_ptr np5 = new node(); 
     node_ptr np6 = new node(); 
     node_ptr np7 = new node(); 

     np0->val = 5; 
     np1->val = 3; 
     np2->val = 1; 
     np3->val = 4; 
     np4->val = 6; 
     np5->val = 9; 
     np6->val = 7; 
     np7->val = 10; 

     np0->left = np1; 
     np1->left = np2; 
     np1->right = np3; 

     np0->right = np4; 
     np4->right = np5; 

     np5->left = np6; 
     np5->right = np7; 


     TreetoQueue(np0); 


} 
+0

我预期代码重新安排左右指针指向前者和后继者的顺序(形成双向链表),但不知何故它们保持不变 – bl3e 2012-03-08 09:35:08

+0

@rAkesH在这里工作,指针被转换为他们应该的位置。使用'TreetoQueue'将树转换为双向链表后,我可以遍历列表从左到右,从右到左,从而得到预期的结果。问题在于你没有向我们展示的代码。 – 2012-03-08 10:47:25

+0

@DanielFischer是的,它确实有效!我的坏。现在我不得不改变根目录开始的列表,我用一个辅助函数返回最左边的树节点,并调用TreetoQueue。 – bl3e 2012-03-08 12:30:13

0

我已经写了什么,我认为是一种更简单,更优雅的解决方案仍扮演一个递归序遍历的想法,但并不需要在每个呼叫分配任何内存:

Node* Inorder(Node* _n, Node*& _listHead, Node* _lastP=NULL){ 
    if (_n->left) 
    _lastP = Inorder(_n->left, _listHead, _lastP); 
    if (_lastP){ 
    _lastP->right = _n; 
    _n->left = _lastP; 
    }else 
    _listHead = _n; 
    if (_n->right) 
    return Inorder(_n->right, _listHead, _n); 
    return _n; 
} 

的想法是跟踪被添加到列表中的最后一个元素(_lastP)。在写入代码时,代码将销毁二叉搜索树结构而不是已排序的双链表。

下面是完整的代码:

#include <iostream> 
using namespace std; 
struct Node{ 
    int data; 
    Node* left; 
    Node* right; 
    Node(int _d=0):data(_d),left(NULL),right(NULL){} 
}; 

Node* Inorder(Node* _n, Node*& _listHead, Node* _lastP=NULL){ 
    if (_n->left) 
    _lastP = Inorder(_n->left, _listHead, _lastP); 
    if (_lastP){ 
    _lastP->right = _n; 
    _n->left = _lastP; 
    }else 
    _listHead = _n; 
    if (_n->right) 
    return Inorder(_n->right, _listHead, _n); 
    return _n; 
} 

Node* BSTtoSortedDoublyLinkedList(Node* _treeRoot){ 
    if(!_treeRoot) 
    return NULL; 
    Node* listHead = NULL; 
    Node* listTail = Inorder(_treeRoot, listHead); 
    //could make circular with following lines 
    //listHead->left = listTail; listTail->right = listHead; 
    return listHead; 
} 

int main(){ 
    //create our tree 
    Node* root = new Node(5); 
    Node* n1 = new Node(3); 
    Node* n2 = new Node(1); 
    Node* n3 = new Node(4); 
    Node* n4 = new Node(6); 
    Node* n5 = new Node(9); 
    Node* n6 = new Node(7); 
    Node* n7 = new Node(10); 

    root->left = n1; 
    n1->left = n2; 
    n1->right = n3; 
    root->right = n4; 
    n4->right = n5; 
    n5->left= n6; 
    n5->right = n7; 
    /* 

     _______5______ 
     /   \ 
    ___3__    6__ 
    / \    \ 
    1  4    _9 
         /\ 
          7 10 
    */ 

    Node* linkedList = BSTtoSortedDoublyLinkedList(root); 
    while(linkedList){ 
    cout << linkedList->data << " "; 
    linkedList = linkedList->right; 
    } 
    return 0; 
}