这是一个将二进制搜索树转换为已排序的双向链表的函数。想法是进行顺序遍历并将访问节点放在大小为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;
}
答案 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;
}