1. 程式人生 > >將搜尋二叉樹轉換成雙向連結串列

將搜尋二叉樹轉換成雙向連結串列

題目


對二叉樹的節點來說, 有本身的值域, 有指向左孩子和右孩子的兩個指標; 對雙向連結串列的節點來說,有本身的值域, 有指向上一個節點和下一個節點的指標。 在結構上, 兩種結構有相似性, 現在有一棵搜尋二叉樹, 請將其轉換為一個有序的雙向連結串列。

分析

用兩種方法求解本題。 方法一:由於是搜尋二叉樹,直接求出其中序遍歷序列,構造雙向連結串列即可。
方法二:採用遞迴實現。分別得到左右子樹的雙向子連結串列(儲存該子連結串列的尾節點,並使該尾節點的next連結子連結串列的頭節點,效能優化,避免線性查詢),然後將當前節點連結即可。

程式碼

#include <iostream>
#include <cstdlib>
#include <vector>

using namespace std;

//雙向連結串列結構體
struct DListNode {
	int val;
	DListNode *prev, *next;
	DListNode(int v) :val(v), prev(NULL),next(NULL){}
};

//二叉搜尋樹
struct BSTNode {
	int val;
	BSTNode *left, *right;
	BSTNode(int v):val(v),left(NULL),right(NULL){}
};

//二叉搜尋樹插入節點
void insert(BSTNode **root, int val)
{
	if (*root == NULL)
	{
		*root = new BSTNode(val);
		return;
	}

	if (val < (*root)->val)
		insert(&((*root)->left),val);
	else
		insert(&((*root)->right),val);
}

//中序遍歷二叉樹
void inOrder(BSTNode *root, vector<int> &ret)
{
	if (root == NULL)
		return;
	inOrder(root->left, ret);
	ret.push_back(root->val);
	inOrder(root->right, ret);
}

//方法一,利用中序排序得到二叉搜尋樹序列,構造雙向連結串列T(n)=o(n) S(n)=o(n)
DListNode *translate(BSTNode *root)
{
	if (root == NULL)
		return NULL;

	vector<int> inRet;
	inOrder(root, inRet);

	DListNode *head = NULL, *p = NULL;
	for (auto iter = inRet.begin(); iter != inRet.end(); ++iter)
	{
		if (head == NULL)
		{
			head = new DListNode(*iter);
			p = head;
		}//if
		else {
			DListNode *node = new DListNode(*iter);
			node->prev = p;
			p->next = node;

			p = node;
		}//else
	}//for
	return head;
}

//方法二,遞迴實現,T(n)=O(n) S(n)=O(h)
DListNode *translate2(BSTNode *root)
{
	if (root == NULL)
		return NULL;

	//返回構造好連結串列的尾節點,並使得尾節點的next指向頭結點
	DListNode *lEnd = translate2(root->left);
	DListNode *rEnd = translate2(root->right);

	DListNode *lHead = NULL;
	DListNode *rHead = NULL;
	if (lEnd)
		lHead = lEnd->next;
	if (rEnd)
		rHead = rEnd->next;

	DListNode *node = new DListNode(root->val);
	if (lEnd && rEnd)
	{
		lEnd->next = node;
		node->prev = lEnd;
		node->next = rHead;
		rHead->prev = node;

		rEnd->next = lHead;
	}//if
	else if (lEnd != NULL)
	{
		lEnd->next = node;
		node->prev = lEnd;

		node->next = lHead;
		return node;
	}
	else if (rEnd != NULL)
	{
		node->next = rHead;
		rHead->prev = node;

		rEnd->next = node;
		
		return rEnd;
	}else{
		node->next = node;
		return node;
	}
}

//遍歷雙向連結串列
void display(DListNode *head)
{
	if (head == NULL)
		return;

	DListNode *p = head;
	while (p)
	{
		cout << p->val << "\t";
		p = p->next;
	}//while

	cout << endl;
}

int main()
{
	vector<int> v = { 5,4,6,2,7 };
	BSTNode *root = NULL;

	for (auto iter = v.begin(); iter != v.end(); ++iter)
	{
		insert(&root, *iter);
	}//for

	DListNode *head = translate(root);

	display(head);

	DListNode *end = translate2(root);
	head = end->next;
	end->next = NULL;
	display(head);

	system("pause");
	return 0;
}