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

面试100题系列之1将查找二叉树转换成有序的双向链表

2013-04-30 13:39 741 查看
1、将二元查找树转化成排序的双向链表,题目来源:http://blog.csdn.net/v_JULY_v/article/details/6057286

10

/ \

6 14

/ \ / \

4 8 12 16 => 4<=>6<=>8<=>10<=>12<=>16

要求:不能创建节点,只改变指针的指向

方法:其实就是树的中序遍历。用递归的方法build树,然后再将遍历到的节点一个一个的加到链表中去。
#include<stdio.h>
#include<string.h>
struct NODE
{
int data;
NODE *Left;
NODE *Right;
};
const int N = 20;
NODE node
;
int top;
void Add(NODE *root, int v)
{
if(!root)
return;
if(root->data < v)
{
if(root->Right)
Add(root->Right, v);
else
{
root->Right = &node[++top];
node[top].data = v;
}
}
else if(root->data > v)
{
if(root->Left)
Add(root->Left, v);
else
{
root->Left = &node[++top];
node[top].data = v;
}
}
else
printf("重复加入节点%d\n", v);
}
//转化之后链表是降序排列的
NODE *TransTreeToLink(NODE *root)
{
if(!root)
return NULL;
NODE *stack
;
int top = -1;
NODE *p = root;
NODE *head = NULL;
while(p != NULL || top > -1)
{
while(p != NULL)
{
stack[++top] = p;
p = p->Left;
}
if(top > -1)
{
p = stack[top]->Right;
if(!head)
head = stack[top];
else
{
//实现与链表的链接,先连,后断
stack[top]->Left = head;
head->Right = stack[top];
head = stack[top];
}
--top;
}
}
return head;
}
//打印链表
void Print(NODE *head)
{
if(!head)
return;
NODE *p;
p = head;
while(p != NULL)
{
printf("%d ",p->data);
p = p->Left;
}
printf("\n");
}

int main()
{
int n,i,v;
NODE *head;
while(scanf("%d", &n) != EOF)
{
memset(node, 0, sizeof(node));
top = 0;
scanf("%d", &v);
node[0].data = v;
for(i = 1; i < n; ++i)
{
scanf("%d", &v);
Add(&node[0], v);
}
head = TransTreeToLink(&node[0]);
Print(head);
}
}
PS:附上以前写得很挫的代码:两个关于NODE的定义都是一样的。
/*****************************************************************************
*1、将二元查找树转化成排序的双向链表
*			  10
*			 /  \
*			6	 4
*		   / \  / \
*		  4  8 12 16  => 4<=>6<=>8<=>10<=>12<=>16
*要求:不能创建节点,只改变指针的指向
*方法:递归和栈。其实就是树的中序遍历。
******************************************************************************/
//将节点加入树中间
bool AddNodeToTree(TREENODE* &pRoot, int Value)
{
if(NULL == pRoot)
{
TREENODE *pTemp;
pTemp = (TREENODE *)malloc(sizeof(TREENODE));
if(NULL == pTemp)
{
printf("加入节点%d失败。", Value);
}
pTemp->Data = Value;
pTemp->left = NULL;
pTemp->right = NULL;
pRoot = pTemp;
return true;
}
if(Value < pRoot->Data)
{
AddNodeToTree(pRoot->left, Value);
}
else if(Value > pRoot->Data)
{
AddNodeToTree(pRoot->right, Value);
}
else
{
printf("重复加入节点%d\n", Value);
return false;
}
}
//将节点转化成有序链表
TREENODE *TransTreeToLink(TREENODE *pRoot)
{
if(!pRoot)
{
return NULL;
}

TREENODE *pTemp;
//记录链表中的头结点
TREENODE *pList = NULL;
TREENODE *Stack[MAX_SIZE];
int top = -1;

//将根节点的左、右及自己入栈
if(pRoot->right != NULL)
{
Stack[++top] = pRoot->right;
}
Stack[++top] = pRoot;
if(pRoot->left != NULL)
{
Stack[++top] = pRoot->left;
}

while(top > -1)
{
pTemp = Stack[top];
--top;
if(NULL == pTemp->left && NULL == pTemp->right)
{
//如果是第一个进入链表的节点
pTemp->left = pList;
if(pList != NULL)
{
pList->right = pTemp;
}

//判断是否栈中只有最后一个节点未入链表
if(top >= 0)
{
//链表和树之间的连接
pTemp->right = Stack[top];
Stack[top]->left = pTemp;
//更新链表头节点
pList = Stack[top];
--top;
}
else
{
pList = pTemp;
}
}//end if(NULL == pTemp->left && NULL == pTemp->right)
//如果不是第一个入链表的节点
else
{
if(pTemp->right != NULL)
{
Stack[++top] = pTemp->right;
}
Stack[++top] = pTemp;
if(pTemp->left != NULL)
{
Stack[++top] = pTemp->left;
}
}//end else
}//end while(top > -1)
return pList;
}
//打印链表
void Print(TREENODE *pList)
{
if(pList ==NULL)
{
return;
}
TREENODE *pTemp;
pTemp = pList;
while(pTemp != NULL)
{
printf("%d\t", pTemp->Data);
pTemp = pTemp->left;
}
}
//销毁链表
void Destroy(TREENODE *pList)
{
if(pList == NULL)
{
return;
}
TREENODE *pTemp;

while(pList != NULL)
{
pTemp = pList;

pList = pList->left;
free(pTemp);
pTemp = NULL;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: