zoukankan      html  css  js  c++  java
  • 把二元查找树转变成排序的双向链表

    题目:
    输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
    要求不能创建任何新的结点,只调整指针的指向。
    10
    / \
    6 14
    / \ / \
    4 8 12 16
    转换成双向链表
    4=6=8=10=12=14=16。
    首先我们定义的二元查找树节点的数据结构如下:
    struct BSTreeNode
    {
    int m_nValue; // value of node
    BSTreeNode *m_pLeft; // left child of node
    BSTreeNode *m_pRight; // right child of node
    };

    思想:

    1.构造二叉查找树;
    2.中序遍历二叉查找树,因此结点按从小到大顺序访问,假设之前访问过的结点已经调整为一个双向链表,那么只需要将当前结点连接至双向链表的最后一个结点即可,访问完后,双向链表也就调整完了

    代码:

    // 1:构造二叉查找树;
    // 2:中序遍历二叉查找树,因此结点按从小到大顺序访问,假设之前访问过的结点已经调整为一个双向链表,那么
    //       只需要将当前结点连接至双向链表的最后一个结点即可,访问完后,双向链表也就调整完了
    #include<iostream>
    using namespace std;
    struct BSTreeNode
    {
        int m_nValue;         // value of node
        BSTreeNode *m_pLeft;  // left child of node
        BSTreeNode *m_pRight; // right child of node
    };
     
    BSTreeNode *pHead=NULL;//指向循环队列头结点
    BSTreeNode *pIndex=NULL;//指向前一个结点
    
    /* 建立二叉排序树 */
    void addBSTreeNode(BSTreeNode *&pCurrent,int value)//在这个函数中会要改变指针值,一定要记得使用引用传递
    {
        if (pCurrent==NULL)
        {
            BSTreeNode* pBSTree=new BSTreeNode();
            pBSTree->m_nValue=value;
            pBSTree->m_pLeft=NULL;
            pBSTree->m_pRight=NULL;
            pCurrent=pBSTree;
        }
        else if (pCurrent->m_nValue<value)
        {
            addBSTreeNode(pCurrent->m_pRight,value);
        }
        else if (pCurrent->m_nValue>value)
        {
            addBSTreeNode(pCurrent->m_pLeft,value);
        }
        else
        {
            cout<<"node repeated"<<endl;
        }
     
    }
    
    /* 调整结点指针 */
    void convertToDoubleList(BSTreeNode* pCurrent)
    {
        pCurrent->m_pLeft=pIndex;//使当前结点的左指针指向双向链表中最后一个结点
        if (NULL==pIndex)        //若最后一个元素不存在,此时双向链表尚未建立,因此将当前结点设为双向链表头结点
            pHead=pCurrent;
        else//使双向链表中最后一个结点的右指针指向当前结点
            pIndex->m_pRight=pCurrent;
     
        pIndex=pCurrent;//将当前结点设为双向链表中最后一个结点
        cout<<pCurrent->m_nValue<<" ";
    }
    
    /* 中序遍历二叉树,同时调整结点指针                                                                     */
    void inOrderBSTree(BSTreeNode* pBSTree)
    {
        if (NULL==pBSTree)
            return;
        if (NULL!=pBSTree->m_pLeft)
            inOrderBSTree(pBSTree->m_pLeft);
            
        convertToDoubleList(pBSTree);
     
        if (NULL!=pBSTree->m_pRight)
            inOrderBSTree(pBSTree->m_pRight);
    }
     
    int main()
    {
        BSTreeNode *pRoot=NULL;
        
        int a[7];
        for(int i=0;i<7;i++)
        {
            cin>>a[i];
            addBSTreeNode(pRoot,a[i]);
        }
        /*
        addBSTreeNode(pRoot,10);
        addBSTreeNode(pRoot,6);
        addBSTreeNode(pRoot,14);
        addBSTreeNode(pRoot,4);
        addBSTreeNode(pRoot,8);
        addBSTreeNode(pRoot,12);
        addBSTreeNode(pRoot,16);
        */
        inOrderBSTree(pRoot);
        system("pause");
        return 0;
    }

     附:看到一个这样写才恍然大悟。。中序遍历解决之:

    /*
    *问题:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
    *要求不能创建任何新的结点,只调整指针的指向。
    *4=6=8=10=12=14=16
    */
    
    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <string>
    using namespace std;
    
    struct BSTreeNode
    {
        int value;
        BSTreeNode * left;
        BSTreeNode * right;
    };
    
    BSTreeNode * pListHead = NULL;//建立双向链表的头指针,指向双链表的头
    BSTreeNode * pListTail = NULL;//建立双向链表的尾指针,指向双链表的尾
    
    BSTreeNode *BSTreeInsert(BSTreeNode * pRoot,int value)
    {
        //为新节点申请空间并初始化
        BSTreeNode *pNode = new BSTreeNode();
        if(pNode != NULL)
        {
            pNode->value = value;
            pNode->left = NULL;
            pNode->right = NULL;
        }
        else
        {   cout<<"申请内存失败!"<<endl;}
    
        BSTreeNode * pCur = pRoot;//移动指针,用来找到当前节点要插入的位置
        BSTreeNode * pParent = NULL;//移动指正,始终指向pCur的节点的父节点
    
        if(pRoot == NULL)//当前树为空树时
        {
            pRoot = pNode;
        }
        else//当前树不为空树时
        {
            while(pCur != NULL)//查找当前节点在二叉查找树中应该插入的位置,pCur指向应该插入的位置,pParent指向应该插入的位置的父节点
            {
                pParent = pCur;
                if(pCur->value <= pNode->value)
                {
                    pCur = pCur->right;
                }
                else
                {
                    pCur = pCur->left;
                }
            }
            if(pNode->value <= pParent->value)
            {
                pParent->left = pNode;
            }
            else
            {
                pParent->right = pNode;
            }
        }
        return pRoot;
    }
    
    void BSTree2List(BSTreeNode * pCur)
    {
        if(pCur == NULL)
            return;
        if(pListHead == NULL)//双链表头指针指向NULL,此时双链表尚未建立,使pHead指向pCur
        {
            pListHead = pCur;
            pListTail = pCur;
            pCur->left = NULL;
        }
        else
        {
            pListTail->right = pCur;
            pCur->left = pListTail;
            pListTail = pCur;
        }
    }
    
    void InOrderBSTree(BSTreeNode * pRoot)
    {
        BSTreeNode * pCur = pRoot;
        if(pCur != NULL)
        {
            InOrderBSTree(pCur->left);
            //二叉查找树当前节点链接到双向链表中
            BSTree2List(pCur);
            InOrderBSTree(pCur->right);
        }
    }
    
    void BSTreeNodeDestory(BSTreeNode * pListHead)
    {
        BSTreeNode *pCur = pListHead;
        pListHead = NULL;
        while(pCur != NULL)
        {
            BSTreeNode * pDel = pCur;
            pCur = pCur->left;
            delete pCur;
            pCur = NULL;
        }
    }
    int main(int args,char ** argv)
    {
        int array[] = {6,8,4,14,16,10,12};
        int len = sizeof(array)/sizeof(int);
    
        BSTreeNode * pRoot = NULL;//建立二叉查找树根节点
        //建立二叉查找树
        //遍历数组中的每个元素,将每个元素作为一个树节点,插入到二叉查找树中
        for(int i = 0;i < len;++i)
        {
            cout<<array[i]<<"  ";
            pRoot = BSTreeInsert(pRoot,array[i]);
        }
        cout<<endl;
        //二叉查找树中序遍历
        InOrderBSTree(pRoot);
        //打印双向链表
        BSTreeNode *pCur = pListHead;
        while(pCur != NULL)
        {
            cout<<pCur->value<<"  ";
            pCur = pCur->right;
        }
        cout<<endl;
        //销毁双向链表
        BSTreeNodeDestory(pListHead);
    
        system("pause");
        return 0;
    }
  • 相关阅读:
    Android开发之基本控件和详解四种布局方式
    Android开发之Activity的创建跳转及传值
    设计模式(十三):从“FQ”中来认识代理模式(Proxy Pattern)
    设计模式(十二):通过ATM取款机来认识“状态模式”(State Pattern)
    设计模式(十一):从文Finder中认识"组合模式"(Composite Pattern)
    设计模式(十):从电影院中认识"迭代器模式"(Iterator Pattern)
    设计模式(八): 从“小弟”中来类比"外观模式"(Facade Pattern)
    设计模式(六):控制台中的“命令模式”(Command Pattern)
    设计模式(三):“花瓶+鲜花”中的装饰者模式(Decorator Pattern)
    设计模式(一):“穿越火线”中的“策略模式”(Strategy Pattern)
  • 原文地址:https://www.cnblogs.com/sooner/p/3028806.html
Copyright © 2011-2022 走看看