二叉树转双链表(微软面试100题001)

题目:


输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。
例如:

10
/ /
6 14
/ / / /
4 8 12 16
转换成双向链表:
4=6=8=10=12=14=16。

solution1

第一个解决方案是答案里面提供的,不算是纯的c语言解法,使用了c++的引用传参数,而且结果也并不是双向链表,而是一个单向链表,代码如下:

<pre><code>

include<stdio.h>

include<stdlib.h>

//定义树节点
typedef struct BSTreeNode{
int m_nValue; //value of node
struct BSTreeNode *m_pleft;
struct BSTreeNode *m_pright;
} BSTreeNode;

typedef BSTreeNode DoubleList;

DoubleList *pHead;
DoubleList *pListIndex;

void convertToDoubleList(BSTreeNode *pCurrent);

//传入父节点指针和value
void addBSTreeNode(BSTreeNode* &pCurrent, int value)
{
if (NULL==pCurrent)
{
//c++使用new
//BSTreeNode *pBSTree=new BSTreeNode();
BSTreeNode *pBSTree=(BSTreeNode *)malloc(sizeof(BSTreeNode));
pBSTree->m_nValue=value;
pBSTree->m_pleft=NULL;
pBSTree->m_pright=NULL;
pCurrent = pBSTree;

}
else
{
    //链接左节点
    if((pCurrent->m_nValue)>value)
    {
        addBSTreeNode(pCurrent->m_pleft,value);
    }
    else if((pCurrent->m_nValue)<value)
    {
        addBSTreeNode(pCurrent->m_pright,value);
    }
    else
    {
        printf("重复的节点\n");
    }

}
//遍历二元查找树
void ergodicBSTree(BSTreeNode *pCurrent){
if(NULL==pCurrent){
return;
}

//有左节点,则进入左节点分支
if(NULL != pCurrent->m_pleft){
    ergodicBSTree(pCurrent->m_pleft);
}

//节点接到链表尾部
convertToDoubleList(pCurrent);

//有右节点,则进入有右节点分支
if(NULL != pCurrent->m_pright){
    ergodicBSTree(pCurrent->m_pright);
}

}

void convertToDoubleList(BSTreeNode *pCurrent){
pCurrent->m_pleft=pListIndex;

if(NULL !=pListIndex)
{
    pListIndex->m_pright =pCurrent;
}
else
{
    pHead=pCurrent;
}
printf("the value is %d\n",pCurrent->m_nValue);

}
int main(){
BSTreeNode *pRoot=NULL;
pListIndex=NULL;
pHead=NULL;
addBSTreeNode(pRoot,10);
addBSTreeNode(pRoot,4);
addBSTreeNode(pRoot,6);
addBSTreeNode(pRoot,8);
addBSTreeNode(pRoot,12);
addBSTreeNode(pRoot,14);
addBSTreeNode(pRoot,15);
ergodicBSTree(pRoot);
printf("the end\n");
return 0;
}
</code></pre>

总结:这段代码需要使用g++来编译

solution2

纯c的代码,第二个solution我比较中意,他构造了一个很清晰的递归原则,转换过程只需要传入根节点,返回链表首节点:

  1. 如果左子树不为null,处理左子树
    1.a)递归转化左子树为双向链表;
    1.b)找出根结点的前驱节点(是左子树的最右的节点)
    1.c)将上一步找出的节点和根结点连接起来
  2. 如果右子树不为null,处理右子树(和上面的很类似)
    1.a)递归转化右子树为双向链表;
    1.b)找出根结点的后继节点(是右子树的最左的节点)
    1.c)将上一步找出的节点和根结点连接起来
  3. 找到最左边的节点并返回

源代码如下:
<pre><code>

include "stdio.h"

include "stdlib.h"

typedef struct Node{
int data;
struct Node *left;
struct Node *right;

}Node;

//新建一颗树,返回根节点
Node * create(){
Node *root;
Node *p4=(Node *)malloc(sizeof(Node));
Node *p8=(Node *)malloc(sizeof(Node));
Node *p6=(Node *)malloc(sizeof(Node));
Node *p12=(Node *)malloc(sizeof(Node));
Node *p16=(Node *)malloc(sizeof(Node));
Node *p14=(Node *)malloc(sizeof(Node));
Node *p10=(Node *)malloc(sizeof(Node));
Node *p1=(Node *)malloc(sizeof(Node));
Node *p5=(Node *)malloc(sizeof(Node));
Node *p18=(Node )malloc(sizeof(Node));
p4->data=4;
p8->data=8;
p6->data=6;
p12->data=12;
p16->data=16;
p14->data=14;
p10->data=10;
p1->data=1;
p5->data=5;
p18->data=18;
p4->left=p1;
p4->right=p5;
p16->right=p18;
p6->left=p4;
p6->right=p8;
p10->left=p6;
p10->right=p14;
p14->left=p12;
p14->right=p16;
root=p10;
return p10;
}
//输入根节点,返回转换成双向链表的子节点的头部
Node
change(Node root){
//base case
if(!root)
return NULL;
//转换左子树,连接到根节点
if(root->left!=NULL){
//找到最小值
Node
left=change(root->left);
for (;left->right!=NULL;left=left->right);
left->right=root;
root->left=left;
}

//转换右子树,根节点连接到右子树
if(root->right!=NULL){
    Node* right=change(root->right);
    for(;right->left!=NULL;right=right->left);
    right->left=root;
    root->right=right;
}
return root;

}

Node * treeto2list(Node *root){
if (root==NULL){
return root;
}
root = change(root);
while (root->left!=NULL)
root = root->left;
return root;
}

int main(){
Node *root=create();
Node *head = treeto2list(root);
Node *tail=NULL;
while(head){
printf("the number is %d\n",head->data);
tail=head;
head=head->right;
}
printf("反向\n");
while(tail){
printf("the number is %d\n",tail->data);
tail=tail->left;
}
return 0;
}
</code></pre>

总结:递归比较难想,要明白这几句的意思:

//找到左子树里面最大值,就是左子树的最右边的值,让他和root的左边双向连接起来
for (;left->right!=NULL;left=left->right);
left->right=root;
root->left=left;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 树的概述 树是一种非常常用的数据结构,树与前面介绍的线性表,栈,队列等线性结构不同,树是一种非线性结构 1.树的定...
    Jack921阅读 4,373评论 1 31
  • B树的定义 一棵m阶的B树满足下列条件: 树中每个结点至多有m个孩子。 除根结点和叶子结点外,其它每个结点至少有m...
    文档随手记阅读 13,012评论 0 25
  • 数据结构与算法--从平衡二叉树(AVL)到红黑树 上节学习了二叉查找树。算法的性能取决于树的形状,而树的形状取决于...
    sunhaiyu阅读 7,579评论 4 32
  • 数据结构和算法--二叉树的实现 几种二叉树 1、二叉树 和普通的树相比,二叉树有如下特点: 每个结点最多只有两棵子...
    sunhaiyu阅读 6,336评论 0 14
  • 四、树与二叉树 1. 二叉树的顺序存储结构 二叉树的顺序存储就是用数组存储二叉树。二叉树的每个结点在顺序存储中都有...
    MinoyJet阅读 1,452评论 0 7