劍指offer之二叉搜索樹和雙向鏈表
1 問題
比如我們搜索二叉樹如下,我們需要變成雙向鏈表
2 分析
我們知道這個(gè)變成雙向鏈接的時(shí)候是按照樹的中序遍歷打印的,我們只需要在中序遍歷打印的時(shí)候操作該節(jié)點(diǎn),我們可以用臨時(shí)變量保存這個(gè)節(jié)點(diǎn),同時(shí)我們也需要單獨(dú)增加一個(gè)鏈表節(jié)點(diǎn)變量,我們需要保證這個(gè)節(jié)點(diǎn)的左邊指向是該鏈表節(jié)點(diǎn),然后該鏈表節(jié)點(diǎn)的右指向是這個(gè)節(jié)點(diǎn),然后我們?cè)侔堰@個(gè)節(jié)點(diǎn)賦值給這個(gè)鏈表節(jié)點(diǎn),就這樣一直移動(dòng)下去即可。
3 代碼實(shí)現(xiàn)
我這里以下面的搜索二叉樹進(jìn)行操作的
4
2 6
1 3 5 7
#include <stdio.h>
#include <stdlib.h>
typedef struct Tree
{
int value;
struct Tree* left;
struct Tree* right;
} Tree;
/*
* 把搜索二叉樹轉(zhuǎn)成雙向鏈表,我們按照中序遍歷
*/
void convertNode(Tree* node, Tree** lastNodeList)
{
if (node == NULL)
return;
Tree* pCurrent = node;
if (pCurrent->left != NULL)
{
convertNode(pCurrent->left, lastNodeList);
}
//這里就要進(jìn)行我們每個(gè)節(jié)點(diǎn)的前后正確的指向了
pCurrent->left = *lastNodeList;
if (*lastNodeList != NULL)
{
(*lastNodeList)->right = pCurrent;
}
*lastNodeList = pCurrent;
if (pCurrent->right != NULL)
{
convertNode(pCurrent->right, lastNodeList);
}
}
/*
* 把翻轉(zhuǎn)好的雙向鏈表尾巴節(jié)點(diǎn)移動(dòng)到鏈表頭
*/
Tree* convert(Tree* node, Tree* lastNodeList)
{
if (node == NULL || lastNodeList == NULL)
{
printf("node is NULL or lastNodeList is NULL\n");
return NULL;
}
Tree* last = NULL;
convertNode(node, &lastNodeList);
//因?yàn)檫@個(gè)時(shí)候lastNodeList已經(jīng)到了雙向鏈表尾巴,我們需要移動(dòng)到鏈表頭
Tree* headNodeList = lastNodeList;
while (headNodeList != NULL && headNodeList->left != NULL)
{
headNodeList = headNodeList -> left;
}
return headNodeList;
}
/*
* 雙向鏈表從左到右打印
*/
void printRightList(Tree* headNodeList)
{
if (headNodeList == NULL)
{
printf("headNodeList is NULL\n");
return;
}
printf("we will print list from left to right\n");
Tree* pCurrent = headNodeList;
while (pCurrent != NULL)
{
printf("value is %d\n", pCurrent->value);
pCurrent = pCurrent->right;
}
}
/*
* 雙向鏈表從右到左打印
*/
void printLeftList(Tree* headNodeList)
{
if (headNodeList == NULL)
{
printf("headNodeList is NULL\n");
return;
}
printf("we will print list from right to left\n");
Tree* pCurrent = headNodeList;
//先把鏈表頭結(jié)點(diǎn)移動(dòng)為鏈表的尾巴
while (pCurrent->right != NULL)
{
//printf("value is %d\n", pCurrent->value);
pCurrent = pCurrent->right;
}
//pCurrent = pCurrent->left;
while (pCurrent != NULL)
{
printf("value is %d\n", pCurrent->value);
pCurrent = pCurrent->left;
}
}
int main(void)
{
Tree *node1 , *node2 , *node3, *node4, *node5, *node6, *node7;
node1 = (Tree *)malloc(sizeof(Tree));
node2 = (Tree *)malloc(sizeof(Tree));
node3 = (Tree *)malloc(sizeof(Tree));
node4 = (Tree *)malloc(sizeof(Tree));
node5 = (Tree *)malloc(sizeof(Tree));
node6 = (Tree *)malloc(sizeof(Tree));
node7 = (Tree *)malloc(sizeof(Tree));
node1->value = 4;
node2->value = 2;
node3->value = 6;
node4->value = 1;
node5->value = 3;
node6->value = 5;
node7->value = 7;
node1->left = node2;
node1->right = node3;
node2->left = node4;
node2->right = node5;
node3->left = node6;
node3->right = node7;
node4->left = NULL;
node4->right = NULL;
node5->left = NULL;
node5->right = NULL;
node6->left = NULL;
node6->right = NULL;
node7->left = NULL;
node7->right = NULL;
Tree* list = (Tree *)malloc(sizeof(Tree));
if (!list)
{
printf("malloc list fail\n");
return -1;
}
Tree* firstNodeList = NULL;
//convertNode(node1, &list);
firstNodeList = convert(node1, list);
if (firstNodeList == NULL)
{
printf("firstNodeList is NULL\n");
return -1;
}
printRightList(firstNodeList);
printLeftList(firstNodeList);
return 0;
}
4 運(yùn)行結(jié)果
we will print list from left to right
value is 0
value is 1
value is 2
value is 3
value is 4
value is 5
value is 6
value is 7
we will print list from right to left
value is 7
value is 6
value is 5
value is 4
value is 3
value is 2
value is 1
value is 0
作者:chen.yu
深信服三年半工作經(jīng)驗(yàn),目前就職游戲廠商,希望能和大家交流和學(xué)習(xí),
微信公眾號(hào):編程入門到禿頭 或掃描下面二維碼
零基礎(chǔ)入門進(jìn)階人工智能(鏈接)