二叉樹轉(zhuǎn)雙鏈表(微軟面試100題001)

題目:


輸入一棵二元查找樹彩扔,將該二元查找樹轉(zhuǎn)換成一個(gè)排序的雙向鏈表。要求不能創(chuàng)建任何新的結(jié)點(diǎn),只調(diào)整指針的指向。
例如:

10
/ /
6 14
/ / / /
4 8 12 16
轉(zhuǎn)換成雙向鏈表:
4=6=8=10=12=14=16舞吭。

solution1

第一個(gè)解決方案是答案里面提供的,不算是純的c語言解法析珊,使用了c++的引用傳參數(shù)羡鸥,而且結(jié)果也并不是雙向鏈表,而是一個(gè)單向鏈表忠寻,代碼如下:

<pre><code>

include<stdio.h>

include<stdlib.h>

//定義樹節(jié)點(diǎn)
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);

//傳入父節(jié)點(diǎn)指針和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
{
    //鏈接左節(jié)點(diǎn)
    if((pCurrent->m_nValue)>value)
    {
        addBSTreeNode(pCurrent->m_pleft,value);
    }
    else if((pCurrent->m_nValue)<value)
    {
        addBSTreeNode(pCurrent->m_pright,value);
    }
    else
    {
        printf("重復(fù)的節(jié)點(diǎn)\n");
    }

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

//有左節(jié)點(diǎn)惧浴,則進(jìn)入左節(jié)點(diǎn)分支
if(NULL != pCurrent->m_pleft){
    ergodicBSTree(pCurrent->m_pleft);
}

//節(jié)點(diǎn)接到鏈表尾部
convertToDoubleList(pCurrent);

//有右節(jié)點(diǎn),則進(jìn)入有右節(jié)點(diǎn)分支
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>

總結(jié):這段代碼需要使用g++來編譯

solution2

純c的代碼奕剃,第二個(gè)solution我比較中意衷旅,他構(gòu)造了一個(gè)很清晰的遞歸原則,轉(zhuǎn)換過程只需要傳入根節(jié)點(diǎn)纵朋,返回鏈表首節(jié)點(diǎn):

  1. 如果左子樹不為null芜茵,處理左子樹
    1.a)遞歸轉(zhuǎn)化左子樹為雙向鏈表;
    1.b)找出根結(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)(是左子樹的最右的節(jié)點(diǎn))
    1.c)將上一步找出的節(jié)點(diǎn)和根結(jié)點(diǎn)連接起來
  2. 如果右子樹不為null倡蝙,處理右子樹(和上面的很類似)
    1.a)遞歸轉(zhuǎn)化右子樹為雙向鏈表九串;
    1.b)找出根結(jié)點(diǎn)的后繼節(jié)點(diǎn)(是右子樹的最左的節(jié)點(diǎn))
    1.c)將上一步找出的節(jié)點(diǎn)和根結(jié)點(diǎn)連接起來
  3. 找到最左邊的節(jié)點(diǎn)并返回

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

include "stdio.h"

include "stdlib.h"

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

}Node;

//新建一顆樹,返回根節(jié)點(diǎn)
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;
}
//輸入根節(jié)點(diǎn)寺鸥,返回轉(zhuǎn)換成雙向鏈表的子節(jié)點(diǎn)的頭部
Node
change(Node root){
//base case
if(!root)
return NULL;
//轉(zhuǎn)換左子樹猪钮,連接到根節(jié)點(diǎn)
if(root->left!=NULL){
//找到最小值
Node
left=change(root->left);
for (;left->right!=NULL;left=left->right);
left->right=root;
root->left=left;
}

//轉(zhuǎn)換右子樹,根節(jié)點(diǎn)連接到右子樹
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>

總結(jié):遞歸比較難想胆建,要明白這幾句的意思:

//找到左子樹里面最大值烤低,就是左子樹的最右邊的值,讓他和root的左邊雙向連接起來
for (;left->right!=NULL;left=left->right);
left->right=root;
root->left=left;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末笆载,一起剝皮案震驚了整個(gè)濱河市扑馁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凉驻,老刑警劉巖腻要,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異涝登,居然都是意外死亡雄家,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進(jìn)店門胀滚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來趟济,“玉大人乱投,你說我怎么就攤上這事∏瓯啵” “怎么了戚炫?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長媳纬。 經(jīng)常有香客問我嘹悼,道長,這世上最難降的妖魔是什么层宫? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任杨伙,我火速辦了婚禮,結(jié)果婚禮上萌腿,老公的妹妹穿的比我還像新娘限匣。我一直安慰自己,他們只是感情好毁菱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布米死。 她就那樣靜靜地躺著,像睡著了一般贮庞。 火紅的嫁衣襯著肌膚如雪峦筒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天窗慎,我揣著相機(jī)與錄音物喷,去河邊找鬼。 笑死遮斥,一個(gè)胖子當(dāng)著我的面吹牛峦失,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播术吗,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼尉辑,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了较屿?” 一聲冷哼從身側(cè)響起隧魄,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎隘蝎,沒想到半個(gè)月后购啄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡末贾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年闸溃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了整吆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拱撵。...
    茶點(diǎn)故事閱讀 39,769評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡辉川,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拴测,到底是詐尸還是另有隱情乓旗,我是刑警寧澤,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布集索,位于F島的核電站屿愚,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏务荆。R本人自食惡果不足惜妆距,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望函匕。 院中可真熱鬧娱据,春花似錦、人聲如沸盅惜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽抒寂。三九已至结啼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間屈芜,已是汗流浹背郊愧。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留井佑,地道東北人糕珊。 一個(gè)月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像毅糟,于是被迫代替她去往敵國和親红选。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 樹的概述 樹是一種非常常用的數(shù)據(jù)結(jié)構(gòu)姆另,樹與前面介紹的線性表喇肋,棧,隊(duì)列等線性結(jié)構(gòu)不同迹辐,樹是一種非線性結(jié)構(gòu) 1.樹的定...
    Jack921閱讀 4,452評論 1 31
  • B樹的定義 一棵m階的B樹滿足下列條件: 樹中每個(gè)結(jié)點(diǎn)至多有m個(gè)孩子蝶防。 除根結(jié)點(diǎn)和葉子結(jié)點(diǎn)外,其它每個(gè)結(jié)點(diǎn)至少有m...
    文檔隨手記閱讀 13,219評論 0 25
  • 數(shù)據(jù)結(jié)構(gòu)與算法--從平衡二叉樹(AVL)到紅黑樹 上節(jié)學(xué)習(xí)了二叉查找樹明吩。算法的性能取決于樹的形狀间学,而樹的形狀取決于...
    sunhaiyu閱讀 7,648評論 4 32
  • 數(shù)據(jù)結(jié)構(gòu)和算法--二叉樹的實(shí)現(xiàn) 幾種二叉樹 1、二叉樹 和普通的樹相比,二叉樹有如下特點(diǎn): 每個(gè)結(jié)點(diǎn)最多只有兩棵子...
    sunhaiyu閱讀 6,460評論 0 14
  • 四、樹與二叉樹 1. 二叉樹的順序存儲(chǔ)結(jié)構(gòu) 二叉樹的順序存儲(chǔ)就是用數(shù)組存儲(chǔ)二叉樹嘿悬。二叉樹的每個(gè)結(jié)點(diǎn)在順序存儲(chǔ)中都有...
    MinoyJet閱讀 1,528評論 0 7