将BST转换为已排序的双向链表(Debug)

时间:2012-03-07 22:35:51

标签: c++ c algorithm binary-tree

这是一个将二进制搜索树转换为已排序的双向链表的函数。想法是进行顺序遍历并将访问节点放在大小为2的圆形数组中。然后调整左右指针以进行转换双向链接列表。当前节点的右指针永远不会被修改并在以后访问。问题出在哪里?

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 

编辑:它按预期工作。只是我必须将根更改为列表的开头。我使用另一个函数来执行此操作。我可以在没有额外功能的情况下实现此目的吗?

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

2 个答案:

答案 0 :(得分:0)

重申Daniel所说的,以下测试代码(按照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);


}

答案 1 :(得分: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;
}