您的位置:首页 > 职场人生

把二元查找树转变成排序的双向链表

2012-07-27 20:47 429 查看

树、链表

(二叉查找树、双向链表)

一、题目:(感谢 http://blog.csdn.net/v_JULY_v 提供的题目)
把二元查找树转变成排序的双向链表
输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
要求不能创建任何新的结点,只调整指针的指向。
            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.通过上述数组构成二叉查找树
3.再通过二叉查找树的根节点中序遍历整棵树构成双向链表

三、代码:

#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
};

struct DLListNode
{
    int data; //data of node
    DLListNode * prior; //prior point of node
    DLListNode * next; //next point of node
};

class BSTNDLL //Binary search tree and Doubly linked list
{
public :
    //Binary search tree
    void CreateBST(int intArray[],int size); //create a binary search tree by the data in a char array
    void CoutTAll();//cout all data in BSTree
    void CoutTNode(BSTreeNode *node);//cout a node in BSTree
    BSTreeNode * InsertBST(BSTreeNode *root,BSTreeNode *node);//insert a node in BSTree

    //Doubly linked list
    void InsertDLL(DLListNode *node);//insert a node in DLList
    void CoutLAll();//cout all data in DLList
private :
    BSTreeNode *root;
    DLListNode *head;
    int t_size;
};

void BSTNDLL::CoutLAll()
{
    if(t_size == 10)
    {
        head = head->next;
    }
    if(t_size > 0)
    {
        cout<<head->data<<endl;
        head = head->next;
        t_size--;
        CoutLAll();
    }
}

void BSTNDLL::InsertDLL(DLListNode *node)
{
    if(head == NULL)
    {
        head = node;
        head->next = node;
        head->prior = node;
    }else
    {
        node->prior = head;
        node->next = head->next;
        head->next->prior = node;
        head->next = node;
        head = head->next;
    }
}

void BSTNDLL::CreateBST(int intArray[],int size)
{
    root = NULL;
    head = NULL;
    t_size = size;
    for(int i=0;i<size;i++)
    {
        BSTreeNode *node = new BSTreeNode;
        node->m_nValue = intArray[i];
        node->m_pLeft = node->m_pRight = NULL;
        root = InsertBST(root,node);
    }
}

void BSTNDLL::CoutTAll()
{
    CoutTNode(root);
}

BSTreeNode * BSTNDLL::InsertBST(BSTreeNode *n_root,BSTreeNode *node)
{
    if(n_root == NULL)
    {
        n_root = node;
    }else if(node->m_nValue < n_root->m_nValue)
    {
        n_root->m_pLeft = InsertBST(n_root->m_pLeft,node);
    }else
    {
        n_root->m_pRight = InsertBST(n_root->m_pRight,node);
    }
    return n_root;
}

void BSTNDLL::CoutTNode(BSTreeNode *node)
{
    if(node->m_pLeft != NULL)
    {
        CoutTNode(node->m_pLeft);
    }
    //cout<<node->m_nValue<<endl;

    DLListNode * dll_node = new DLListNode;
    dll_node->data = node->m_nValue;
    dll_node->next = dll_node->prior = NULL;
    InsertDLL(dll_node);

    if(node->m_pRight != NULL)
    {
        CoutTNode(node->m_pRight);
    }
}

void main()
{
    BSTNDLL bstNdll;
    int a[] = {10,6,14,4,8,12,16,23,43,1};
    bstNdll.CreateBST(a,10);
    bstNdll.CoutTAll();
    bstNdll.CoutLAll();
}


四、代码分析:
1.往二叉查找树插入数据

BSTreeNode * BSTNDLL::InsertBST(BSTreeNode *n_root,BSTreeNode *node)
{
if(n_root == NULL)
{
n_root = node;
}else if(node->m_nValue < n_root->m_nValue)
{
n_root->m_pLeft = InsertBST(n_root->m_pLeft,node);
}else
{
n_root->m_pRight = InsertBST(n_root->m_pRight,node);
}
return n_root;
}


思路:

(1)如被插节点为空,把节点赋给被插结点

(2)如节点值小于被插节点的左子树值,把节点插入被插节点的左子树

(3)否则把节点插入被插节点的左子树

2.往双向链表插入数据

void BSTNDLL::InsertDLL(DLListNode *node)
{
if(head == NULL)
{
head = node;
head->next = node;
head->prior = node;
}else
{
node->prior = head;
node->next = head->next;
head->next->prior = node;
head->next = node;
head = head->next;
}
}


思路:

在结点h后插入一个结点n,需要修改四个指针
(1)n->prior = h;
(2)n->next = h->next;
(3)h->next->prior = n;
(4)h->next = n;

五、改进:
看到网上很多资料,发现这个题目并不是要求构建两个结构体(先构建一棵树后再构建一个双向链表)
而是通过调整树的指针令其变为双向链表(由始至终只有一个结构体),OMG~

 5.1.题目分析:

(1) 建立查找二叉树

(2) 设定双向链表的头指针 *head 和尾指针 *last

(3) 中序遍历二叉查找树(顺序输出)时,调用 changeBSTtoDLL() 函数,调整查找二叉树的指针指向

5.2.代码:

//中序遍历
void BSTNDLL::CoutTNode(BSTreeNode *node)
{
if(node->m_pLeft != NULL)
{
CoutTNode(node->m_pLeft);
}

//cout<<node->m_nValue<<endl;

changeBSTtoDLL(node);

if(node->m_pRight != NULL)
{
CoutTNode(node->m_pRight);
}
}

//调整查找二叉树指针指向
void BSTNDLL::changeBSTtoDLL(BSTreeNode *node)
{
if(head == NULL && last == NULL)
{
head = last = node;
}
else{
node->m_pLeft = last;   //使当前左节点指向双向链表的最后一位
last->m_pRight = node;  //把双向链表的最后一位右节点指向当前节点
last = node;            //把当前节点设置为双向链表的最后一位
}
}


5.3.代码分析:

调整查找二叉树指针指向思路:

使当前左节点指针指向last,last右节点指针指向当前节点,把当前节点赋值给last

即:

1.使当前左节点指向双向链表的最后一位;
node->m_pLeft = last;


2.把双向链表的最后一位右节点指向当前节点;
last->m_pRight = node;


3.把当前节点设置为双向链表的最后一位。
last = node;


六、总结:

    在本题目中,我清楚认识到查找二叉树、双向链表的构造,如何使用代码建立查找二叉树和双向链表,同时认识到二叉查找树和双向链表的结构的相同之处,能通过简单地通过调整指针的指向进行互换。

#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
};

struct DLListNode
{
int data; //data of node
DLListNode * prior; //prior point of node
DLListNode * next; //next point of node
};

class BSTNDLL //Binary search tree and Doubly linked list
{
public :
//Binary search tree
void CreateBST(int intArray[],int size); //create a binary search tree by the data in a char array
void CoutTAll();//cout all data in BSTree
void CoutTNode(BSTreeNode *node);//cout a node in BSTree
BSTreeNode * InsertBST(BSTreeNode *root,BSTreeNode *node);//insert a node in BSTree

//Doubly linked list
void CoutLAll();//cout all data in DLList

//Change a BSTree to DLList
void changeBSTtoDLL(BSTreeNode *node);

private :
BSTreeNode *root;
BSTreeNode *head;
BSTreeNode *last;
int t_size;

};

void BSTNDLL::CoutLAll()
{
if(t_size > 0)
{
cout<<head->m_nValue<<endl;
head = head->m_pRight;
t_size--;
CoutLAll();
}
}

void BSTNDLL::CreateBST(int intArray[],int size)
{
root = NULL;
head = NULL;
last = NULL;
t_size = size;
for(int i=0;i<size;i++)
{
BSTreeNode *node = new BSTreeNode;
node->m_nValue = intArray[i];
node->m_pLeft = node->m_pRight = NULL;
root = InsertBST(root,node);
}
}

void BSTNDLL::CoutTAll()
{
CoutTNode(root);
last->m_pRight = head;
}

BSTreeNode * BSTNDLL::InsertBST(BSTreeNode *n_root,BSTreeNode *node) { if(n_root == NULL) { n_root = node; }else if(node->m_nValue < n_root->m_nValue) { n_root->m_pLeft = InsertBST(n_root->m_pLeft,node); }else { n_root->m_pRight = InsertBST(n_root->m_pRight,node); } return n_root; }

void BSTNDLL::CoutTNode(BSTreeNode *node)
{
if(node->m_pLeft != NULL)
{
CoutTNode(node->m_pLeft);
}

//cout<<node->m_nValue<<endl;

changeBSTtoDLL(node);

if(node->m_pRight != NULL)
{
CoutTNode(node->m_pRight);
}
}

void BSTNDLL::changeBSTtoDLL(BSTreeNode *node)
{
if(head == NULL && last == NULL)
{
head = last = node;
}
else{
node->m_pLeft = last;
last->m_pRight = node;
last = node;
}
}

void main()
{
BSTNDLL bstNdll;
int a[] = {10,6,14,4,8,12,16,23,43,1};
bstNdll.CreateBST(a,10);
bstNdll.CoutTAll();
bstNdll.CoutLAll();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息