二叉搜索树与双向链表——27

来源:互联网 发布:linux cp 带目录结构 编辑:程序博客网 时间:2024/06/02 02:41

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

wKiom1dIRfrxQCSkAAAJnPK-y1I749.png

如上所示的二叉搜索树,转换成排序的双向链表就是5-><-6-><-7-><-8-><-9-><-10-><-11。


    因为要求转换成双向链表,而恰好二叉树的每个结点都有两个指针,因此可以直接调整指针的指向;对于搜索二叉树,每个结点的左子树的值都比根结点的值要小,而每个右子树的值都比当前结点的值要大,而要求转换成排序的双向链表,因此,对于每个结点的访问顺序应当是先左再中后右,也就是用中序遍历的思路,这样才能保证是有序的;

    对于指针的指向,可以将每个结点指向左结点的指针看做双向链表中指向前一个结点的prev指针,而每个结点指向右结点的指针看做双向链表中指向下一个结点的next指针;因此,对于搜索二叉树的最左结点,其实也就是树中的最小值,也就是双向链表的头结点,而树的最右结点就是链表的尾结点也就是最大值;

    观察可发现,对于根结点来说,其prev应该指向的是左子树的最右结点,而next应该指向的是右子树的最左结点,因此对于整棵树来说,可以划分成左右子树来进行递归;


程序设计如下:

#include <iostream>#include <assert.h>using namespace std;struct BinaryTreeNode//二叉树结点结构体{    int _val;    BinaryTreeNode *_Lnode;    BinaryTreeNode *_Rnode;    BinaryTreeNode(int val)//构造函数        :_val(val)         ,_Lnode(NULL)         ,_Rnode(NULL)    {}  };//创建二叉搜索树,这里简便直接使用前序遍历的方式结构造出了二叉搜索树BinaryTreeNode* _Create(const int *arr, size_t& index, size_t size){    if((index < size) && (arr[index] != '#'))    {           BinaryTreeNode* root = new BinaryTreeNode(arr[index]);        root->_Lnode = _Create(arr, ++index, size);        root->_Rnode = _Create(arr, ++index, size);        return root;    }       else        return NULL;}BinaryTreeNode* CreateBinaryTree(const int *arr, size_t size){    assert(arr && size);    size_t index = 0;    return _Create(arr, index, size);}//销毁转变之后的双向链表void DestoryBinaryTree(BinaryTreeNode* ListNode){    BinaryTreeNode* tmp = ListNode;    while(ListNode != NULL)    {        tmp = ListNode;        ListNode = ListNode->_Lnode;        delete tmp;    }}//前序遍历检验二叉树void PrevOrder(BinaryTreeNode *root){    if(root != NULL)    {        cout<<root->_val<<" ";        PrevOrder(root->_Lnode);        PrevOrder(root->_Rnode);    }}//二叉搜索树转换为双向链表void BSTToList(BinaryTreeNode* root, BinaryTreeNode** lastnode){    if(root != NULL)    {        BSTToList(root->_Lnode, lastnode);        root->_Lnode = *lastnode;//如果左结点为空,则当前结点的前指针指向当前链表的最后一个结点        if(*lastnode != NULL)            (*lastnode)->_Rnode = root;//将当前链表的最后一个结点的next指针设置为当前结点        *lastnode = root;//将链表的最后一个结点更新为当前结点        BSTToList(root->_Rnode, lastnode);//继续遍历右子树直至为空    }}void PrintList(BinaryTreeNode* ListNode){    assert(ListNode);    BinaryTreeNode* tmp = ListNode;    cout<<"ListHead:"<<tmp->_val<<endl;    cout<<"正向打印链表:";    while(tmp->_Rnode != NULL)//每个结点的右指针指向下一个结点    {        cout<<tmp->_val<<"->";        tmp = tmp->_Rnode;    }    cout<<tmp->_val<<"->NULL"<<endl;    cout<<"ListTail:"<<tmp->_val<<endl;    cout<<"逆向打印链表:";    while(tmp->_Lnode != NULL)//每个结点的左指针指向前一个结点    {        cout<<tmp->_val<<"->";        tmp = tmp->_Lnode;    }    cout<<tmp->_val<<"->NULL"<<endl;}int main(){    int arr[] = {8,6,5,'#','#',7,'#','#',10,9,'#','#',11,'#','#'};    BinaryTreeNode* root = CreateBinaryTree(arr, sizeof(arr)/sizeof(arr[0]));    cout<<"PrevOrder: ";    PrevOrder(root);    cout<<endl;    BinaryTreeNode* lastnode = NULL;    BSTToList(root, &lastnode);    BinaryTreeNode* ListNode = root;    while(ListNode->_Lnode != NULL)//获取链表的头结点        ListNode = ListNode->_Lnode;    PrintList(ListNode);    DestoryBinaryTree(ListNode);    return 0;}


运行程序:

wKioL1dPuhDiRkoVAAAgm4YgYHo622.png



《完》

本文出自 “敲完代码好睡觉zzz” 博客,请务必保留此出处http://2627lounuo.blog.51cto.com/10696599/1785449