題目鏈接地址:
http://ac.jobdu.com/problem.php?pid=1503
題目1503:二叉搜索樹與雙向鏈表
時間限制:1 秒內存限制:128 兆特殊判題:否提交:998解決:281
題目描述:
輸入一棵二叉搜索樹,將該二叉搜索樹轉換成一個排序的雙向鏈表。要求不能創建任何新的結點,只能調整樹中結點指針的指向。
輸入:
輸入可能包含多個測試樣例。
對於每個測試案例,輸入的第一行爲一個數n,代表測試樣例的個數。
接下來的n行,每行爲一個二叉搜索樹的先序遍歷序列,其中左右子樹若爲空則用0代替。
輸出:
對應每個測試案例,
輸出將二叉搜索樹轉換成排序的雙向鏈表後,從鏈表頭至鏈表尾的遍歷結果。
樣例輸入:
1
2 1 0 0 3 0 0
樣例輸出:
1 2 3
思路分析
二叉搜索樹左子樹中的結點均小於根結點,右子樹中的結點均大於根結點。二叉搜索樹的中序遍歷序列是有序的。
中序遍歷遞歸實現,每次遞歸都保存一個指向已構造好的雙向鏈表的尾節點的指針,將雙向鏈表的最後一個節點與根節點連接在一起 。
代碼:
自己按照書上寫的,但是老是不能通過所有的用例,最後參考了
http://blog.csdn.net/ns_code/article/details/26623795,寫的很好,直接貼上吧。
#include<stdio.h>
#include<stdlib.h>
typedef struct BSTNode
{
int data;
struct BSTNode *left;
struct BSTNode *right;
}BSTNode,*BSTree;
/*
根據題目要求的格式創建二叉排序樹
*/
void CreateBST(BSTree *pRoot)
{
int data;
scanf("%d",&data);
if(data == 0)
pRoot = NULL;
else
{
*pRoot = (BSTree)malloc(sizeof(BSTNode));
if(*pRoot == NULL)
exit(EXIT_FAILURE);
(*pRoot)->data = data;
(*pRoot)->left = NULL;
(*pRoot)->right = NULL;
CreateBST(&((*pRoot)->left));
CreateBST(&((*pRoot)->right));
}
}
/*
採用中序遍歷的方式將二叉樹轉化爲雙向鏈表,
*pLas指向雙向鏈表的最後一個節點
*/
void ConvertNode(BSTree pRoot,BSTree *pLast)
{
if(pRoot == NULL)
return;
//先轉化左子樹
if(pRoot->left != NULL)
ConvertNode(pRoot->left,pLast);
//將雙向鏈表的最後一個節點與根節點連接在一起
pRoot->left = *pLast;
if(*pLast != NULL)
(*pLast)->right = pRoot;
*pLast = pRoot;
//轉換右子樹
if(pRoot->right != NULL)
ConvertNode(pRoot->right,pLast);
}
/*
返回雙向鏈表的頭結點
*/
BSTree Convert(BSTree pRoot)
{
if(pRoot == NULL)
return NULL;
if(pRoot->left==NULL && pRoot->right==NULL)
return pRoot;
BSTree pLast = NULL;
ConvertNode(pRoot,&pLast);
//返回頭結點
BSTree pHead = pLast;
while(pHead->left != NULL)
pHead = pHead->left;
return pHead;
}
int main()
{
int n;
while(scanf("%d",&n) != EOF)
{
int i;
for(i=0;i<n;i++)
{
BSTree pRoot = NULL;
CreateBST(&pRoot);
BSTree pHead = Convert(pRoot);
while(pHead != NULL)
{
printf("%d ",pHead->data);
pHead = pHead->right;
}
printf("\n");
free(pRoot);
pRoot = NULL;
}
}
return 0;
}