这是第 2 轮亚马逊面试问题。将给定的二叉搜索树转换为预购和后购链表,并且必须进行这种转换。
问问题
2788 次
5 回答
3
下面的代码是为了在不使用堆栈的情况下以 pre-Order 遍历形式对二叉树进行展平。它使用前序遍历递归方法。在此, TreeNode[] arr 将保存我正在更新该节点的右指针的最后一个最左边的节点值。
public TreeNode preorderNode(TreeNode root,TreeNode[] arr)
{
if(root==null)
return null;
if(root!=null && root.left==null && root.right==null)
{
arr[0]=root;
return root;
}
TreeNode temp=root.right;
if(root.left!=null)
root.right=preorderNode(root.left,arr);
else arr[0]=root;
root.left=null;
arr[0].right=preorderNode(temp,arr);
return root;
}
public void flatten(TreeNode root) {
if(root==null || (root.left==null && root.right==null))
return;
TreeNode temp=root.right;
TreeNode[] arr=new TreeNode[1];
arr[0]=null;
if(root.left!= null)
root.right=preorderNode(root.left,arr);
else
arr[0]=root;
root.left=null;
arr[0].right=preorderNode(temp,arr);
}
于 2016-07-03T11:58:18.293 回答
1
要解决预购版本的问题,您可以稍微修改一个简单的预购(请参阅下面的代码查看)。
这个想法是在前序遍历中从二叉搜索树构造一个双向链表。但是,我们只在遍历期间设置前向链接。
让我们通过一个例子来学习。如果树看起来像:
4
/ \
2 6
/ \ / \
1 3 5 7
然后,链表应如下所示:
4 <-> 2 <-> 1 <-> 3 <-> 6 <-> 5 <-> 7。
现在,我们只在前序遍历期间设置前向链接。因此,我们的列表将如下所示。
4 -> 2 -> 1 -> 3 -> 6 -> 5 -> 7
左边或前面的指针(上面未显示)仍然与树中的一样。我们现在可以通过简单的遍历列表来设置左指针。
下面的代码正是这样做的。
#include <iostream>
using namespace std;
class node{
public:
int data;
node * left, *right;
node(int a){
data = a;
left = right = NULL;
}
};
node * head = NULL, *prev = NULL;
void preorder(node * root){
if(!root) return;
//both head and prev aren't set. This node must be the root(and head of our required list).
if(!head and !prev) head = root;
//store the address of root's right child
node * temp = root->right;
/*
If prev is set, make current node it's right child.
(This is why we save right child's address for every node in temp.)
*/
if(prev) prev->right = root;
//now make the current node prev.
prev = root;
cout << root ->data <<" ";
preorder(root->left);
preorder(temp);
}
void printll(){
node * prev = NULL;
while(head != NULL){
cout << head ->data << " ";
head -> left = prev;
head = head -> right;
prev = head;
}
cout<<endl;
}
int main() {
node * t = new node(4);
t->left = new node(2);
t->left->left = new node(1);
t->left->right = new node(3);
t->right = new node(6);
t->right->left = new node(5);
t->right->right = new node(7);
preorder(t);
cout<<endl;
printll();
return 0;
}
于 2014-07-29T08:38:23.800 回答
0
void preorder(struct node *head)
{
if (head)
{
addToLL(head->data);
preorder(head->left);
preorder(head->right);
}
}
在 addToLL() 中,您可以继续将节点添加到链表中。
全球宣言
struct node *llHead;
这样链表头就完好无损。
于 2014-07-28T12:53:56.163 回答
0
以下算法用于预购转换。同样,您可以进行后订购。
struct node
{
int data;
struct node* left;
struct node* right;
};
/Algorithm */
struct node* bintree2listHelper(struct node *root)
{
if (root == NULL)
return root;
if (root->left != NULL)
{
struct node* left = bintree2listHelper(root->left);
int flag =0;
if(left->left == NULL)
{
left->left = left->right;
}
for(;left->left != NULL;)
{
struct node *temp = left;
for (; temp->right!=NULL; )
{
flag = 1;
temp=temp->right;
}
if(flag)
{
temp->left = root->right;
left =left->left;
break;
}
else
{
left =left->left;
}
}
if(!flag)
left->left = root->right;
}
if (root->right!=NULL)
{
struct node* right = bintree2listHelper(root->right);
struct node *temp1= right;
for (; right->left!=NULL; )
{
temp1 =right;
right = right->left;
}
right->left = temp1->right;
}
return root;
}
struct node* bintreeTolist(struct node *root)
{
if (root == NULL)
return root;
root = bintree2listHelper(root);
return (root);
}
struct node* newNode(int data)
{
struct node* new_node = (struct node *)malloc(sizeof(struct node));
new_node->data = data;
new_node->left = new_node->right = NULL;
return (new_node);
}
void printList(struct node *node)
{
while (node!=NULL)
{
printf("%d ", node->data);
node = node->left;
}
printf("\n");
}
int main()
{
typedef struct node node;
node *root = newNode(10);
root->left = newNode(12);
root->right = newNode(15);
root->left->left = newNode(25);
root->left->right = newNode(30);
root->right->left = newNode(36);
root->left->right->left = newNode(78);
root->left->right->right = newNode(77);
node *head = bintreeTolist(root);
// Print the converted list
printList(head);
return 0;
于 2014-08-04T13:36:36.543 回答
0
预购链表
public TreeNode flatten(TreeNode root) {
if(root==null)
return null;
Stack<TreeNode> s=new Stack<TreeNode>();
s.add(root);
while(!s.isEmpty()){
root=s.pop();
if(root.right!=null)
s.add(root.right);
if(root.left!=null)
s.add(root.left);
if(!s.isEmpty())
root.right=s.peek();
else
root.right=null;
root.left=null;
}
return root;
}
上面的代码给出了右指针作为下一个指针的预排序链表,左指针被忽略(即设置为空)。它是对迭代前序遍历代码的轻微修改。
想法是,一旦当前节点的处理完成,栈顶就有链表中当前节点的下一个节点。
于 2016-07-03T11:15:49.767 回答