您的位置:首页 > Web前端

剑指offer 编程题(25):二叉树搜索与双向链表

2017-12-20 16:28 375 查看

题目描述

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

在二叉搜索树中,每个结点都有两个分别指向其左、右子树的指针,左子树结点的值总是小于父结点的值,右子树结点的值总是大于父结点的值。而在双向链表中,每个结点也有两个指针,它们分别指向前一个结点和后一个结点。所以这两种数据结构的结点是一致,二叉搜索树之所以为二叉搜索树,双向链表之所以为双向链表,只是因为两个指针的指向不同而已,通过改变其指针的指向来实现是完全可能的。

例如如下的二叉搜索树,



若采用中序遍历,其遍历顺序为1-2-3-4-5-6-7,通过适当的指针变换操作,可变成的双向有序链表如下:



class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
if(pRootOfTree == nullptr) return nullptr;
TreeNode* pre = nullptr;

convertHelper(pRootOfTree, pre);

TreeNode* res = pRootOfTree;
while(res ->left)
res = res ->left;
return res;
}

void convertHelper(TreeNode* cur, TreeNode*& pre)
{
if(cur == nullptr) return;

convertHelper(cur ->left, pre);

cur ->left = pre;
if(pre) pre ->right = cur;
pre = cur;

convertHelper(cur ->right, pre);

}
};


class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
if (pRootOfTree == NULL)return NULL;
TreeNode *pointer = NULL;
convert2List(pRootOfTree, pointer);
while (pointer->left!=NULL)
{
pointer = pointer->left;
}
return pointer;
}
void convert2List(TreeNode* pRoot,TreeNode *&pointer)
{
if (pRoot == NULL)
{
return;
}
{
if (pRoot->left != NULL)
{
convert2List(pRoot->left,pointer);
}

pRoot->left = pointer;
if (pointer != NULL)
{
pointer->right = pRoot;
}

pointer = pRoot;
if (pRoot->right!=NULL)
{
convert2List(pRoot->right, pointer);
}
}
}
};


可以中序遍历,然后push到一个vector里面,再连接成链表,此方法可以实现,但是违反题目不能创建新空间的规定,属于犯规作弊

class Solution {
public:
vector<TreeNode*> nodes;

void tranverse(TreeNode* pRoot) {
if (nullptr == pRoot)
return;
tranverse(pRoot->left);
nodes.push_back(pRoot);
tranverse(pRoot->right);
}

TreeNode* adjustTree() {
for (int i = 0; i < nodes.size() - 1; ++i)
nodes[i]->right = nodes[i+1];
nodes[nodes.size()-1]->right = nullptr;
for (int i = nodes.size() - 1; i > 0; --i)
nodes[i]->left = nodes[i-1];
nodes[0]->left = nullptr;
return nodes[0];
}

TreeNode* Convert(TreeNode* pRoot)
{
if (nullptr == pRoot)
return nullptr;
tranverse(pRoot);
return adjustTree();
}
};


非递归中序遍历

void inOrder2(BinTree *root)      //非递归中序遍历
{
stack<BinTree*> s;
BinTree *p=root;
while(p!=NULL||!s.empty())
{
while(p!=NULL)
{
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
p=s.top();
cout<<p->data<<" ";
s.pop();
p=p->rchild;
}
}
}


/*
非递归中序遍历,加个指针pre记录上一次出栈值
*/
class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
TreeNode *head = NULL, *pre = NULL;//head 输出,pre记录上一次出栈值
stack<TreeNode*> s;
while (pRootOfTree || !s.empty())
{
while (pRootOfTree)
{
s.push(pRootOfTree);
pRootOfTree = pRootOfTree->left;
}
if (!s.empty())
{
pRootOfTree = s.top();
s.pop();
if (pre != NULL)
{
pre->right = pRootOfTree;
pRootOfTree->left = pre;
}
else//pre为空,表示s第一次出栈,第一次出栈值为最左值,即输出值
{
head = pRootOfTree;
}
pre = pRootOfTree;
pRootOfTree = pRootOfTree->right;
}
}
return head;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: