c语言 二叉树面试题,【数据结构】70_二叉树的经典面试题分析

面试题 一

单结点删除

描述:编写一个函数用于删除二叉树中的所有单度结点

要求:结点删除后,其唯一的子结点替代它的位置

bVbDqch

情形1:结点中包含指向父结点的指针

定义功能:delOdd1(node)

删除 node 为根结点的二叉树中的单度结点

bVbDqcD

编程实验:单度结点的删除

#include

#include "BTreeNode.h"

using namespace std;

using namespace DTLib;

template < typename T >

BTreeNode* createTree()

{

static BTreeNode ns[9];

for(int i=0; i<9; i++)

{

ns[i].value = i;

ns[i].parent = NULL;

ns[i].left = NULL;

ns[i].right = NULL;

}

ns[0].left = &ns[1];

ns[0].right = &ns[2];

ns[1].parent = &ns[0];

ns[2].parent = &ns[0];

ns[1].left = &ns[3];

ns[1].right = NULL;

ns[3].parent = &ns[1];

ns[2].left = &ns[4];

ns[2].right = &ns[5];

ns[4].parent = &ns[2];

ns[5].parent = &ns[2];

ns[3].left = NULL;

ns[3].right = &ns[6];

ns[6].parent = &ns[3];

ns[4].left = &ns[7];

ns[4].right = NULL;

ns[7].parent = &ns[4];

ns[5].left = &ns[8];

ns[5].right = NULL;

ns[8].parent = &ns[5];

return ns;

}

template < typename T >

void printInOrder(BTreeNode* node)

{

if( node != NULL )

{

printInOrder(node->left);

cout << node->value <

printInOrder(node->right);

}

}

template < typename T >

void printDualList(BTreeNode* node)

{

BTreeNode* g = node;

cout << "head -> tail: " << endl;

while( node != NULL )

{

cout << node->value << " ";

g = node;

node = node->right;

}

cout << endl;

cout << "tail -> head: " << endl;

while( g != NULL )

{

cout << g->value << " ";

g = g->left;

}

cout << endl;

}

//----------------------------------------------------------------------

template

BTreeNode* delOdd1(BTreeNode *node)

{

BTreeNode *ret = nullptr;

if (node != nullptr)

{

if (((node->left != nullptr) && (node->right == nullptr)) ||

((node->left == nullptr) && (node->right != nullptr)))

{

BTreeNode *parent = dynamic_cast*>(node->parent);

BTreeNode *child = (node->left != nullptr) ? node->left : node->right;

if (parent != nullptr)

{

BTreeNode *& parent_child = (parent->left == node) ? parent->left : parent->right;

parent_child = child;

child->parent = parent;

}

else

{

child->parent = nullptr;

}

if (node->flag())

{

delete node;

}

ret = delOdd1(child);

}

else

{

delOdd1(node->left);

delOdd1(node->right);

ret = node;

}

}

return ret;

}

int main()

{

BTreeNode* ns = createTree();

printInOrder(ns);

cout << endl;

ns = delOdd1(ns);

printInOrder(ns);

return 0;

}

输出:

3 6 1 0 7 4 2 8 5

6 0 7 2 8

情形2:结点中只包含左右孩子指针

定义功能: delOdd2(node)

删除 node 为根结点的二叉树中的单度结点

bVbDqgO

编程实验:单度结点删除

#include

#include "BTreeNode.h"

using namespace std;

using namespace DTLib;

template < typename T >

BTreeNode* createTree()

{

static BTreeNode ns[9];

for(int i=0; i<9; i++)

{

ns[i].value = i;

ns[i].parent = NULL;

ns[i].left = NULL;

ns[i].right = NULL;

}

ns[0].left = &ns[1];

ns[0].right = &ns[2];

ns[1].parent = &ns[0];

ns[2].parent = &ns[0];

ns[1].left = &ns[3];

ns[1].right = NULL;

ns[3].parent = &ns[1];

ns[2].left = &ns[4];

ns[2].right = &ns[5];

ns[4].parent = &ns[2];

ns[5].parent = &ns[2];

ns[3].left = NULL;

ns[3].right = &ns[6];

ns[6].parent = &ns[3];

ns[4].left = &ns[7];

ns[4].right = NULL;

ns[7].parent = &ns[4];

ns[5].left = &ns[8];

ns[5].right = NULL;

ns[8].parent = &ns[5];

return ns;

}

template < typename T >

void printInOrder(BTreeNode* node)

{

if( node != NULL )

{

printInOrder(node->left);

cout << node->value <

printInOrder(node->right);

}

}

template < typename T >

void printDualList(BTreeNode* node)

{

BTreeNode* g = node;

cout << "head -> tail: " << endl;

while( node != NULL )

{

cout << node->value << " ";

g = node;

node = node->right;

}

cout << endl;

cout << "tail -> head: " << endl;

while( g != NULL )

{

cout << g->value << " ";

g = g->left;

}

cout << endl;

}

//----------------------------------------------------------------------

template

void delOdd2(BTreeNode *&node)

{

if (node != nullptr)

{

if (((node->left != nullptr) && (node->right == nullptr)) ||

((node->left == nullptr) && (node->right != nullptr)))

{

if (node->flag())

{

delete node;

}

node = (node->left != nullptr) ? node->left : node->right;

delOdd2(node);

}

else

{

delOdd2(node->left);

delOdd2(node->right);

}

}

}

int main()

{

BTreeNode* ns = createTree();

printInOrder(ns);

cout << endl;

delOdd2(ns);

printInOrder(ns);

return 0;

}

输出:

3 6 1 0 7 4 2 8 5

6 0 7 2 8

面试题 二

中序线索化二叉树

描述:编写一个函数用于中序线索化二叉树

要求:不允许使用其他数据结构

bVbDqiC

解法一:在中序遍历的同时进行线索化

思路

使用辅助指针,在中序遍历时指向当前结点的前驱结点

访问当前结点时,连接与前驱结点的先后次序

bVbDqjn

定义功能

inOrderThread(node, pre)

node : 根结点,也是中序访问的结点

pre: 为中序遍历时的前驱结点指针

bVbDqjL

编程实验:中序线索化

#include

#include "BTreeNode.h"

using namespace std;

using namespace DTLib;

template < typename T >

BTreeNode* createTree()

{

static BTreeNode ns[9];

for(int i=0; i<9; i++)

{

ns[i].value = i;

ns[i].parent = NULL;

ns[i].left = NULL;

ns[i].right = NULL;

}

ns[0].left = &ns[1];

ns[0].right = &ns[2];

ns[1].parent = &ns[0];

ns[2].parent = &ns[0];

ns[1].left = &ns[3];

ns[1].right = NULL;

ns[3].parent = &ns[1];

ns[2].left = &ns[4];

ns[2].right = &ns[5];

ns[4].parent = &ns[2];

ns[5].parent = &ns[2];

ns[3].left = NULL;

ns[3].right = &ns[6];

ns[6].parent = &ns[3];

ns[4].left = &ns[7];

ns[4].right = NULL;

ns[7].parent = &ns[4];

ns[5].left = &ns[8];

ns[5].right = NULL;

ns[8].parent = &ns[5];

return ns;

}

template < typename T >

void printInOrder(BTreeNode* node)

{

if( node != NULL )

{

printInOrder(node->left);

cout << node->value <

printInOrder(node->right);

}

}

template < typename T >

void printDualList(BTreeNode* node)

{

BTreeNode* g = node;

cout << "head -> tail: " << endl;

while( node != NULL )

{

cout << node->value << " ";

g = node;

node = node->right;

}

cout << endl;

cout << "tail -> head: " << endl;

while( g != NULL )

{

cout << g->value << " ";

g = g->left;

}

cout << endl;

}

template

void inOrderThread(BTreeNode *node, BTreeNode *&pre)

{

if (node != nullptr)

{

inOrderThread(node->left, pre);

node->left = pre;

if (pre != nullptr)

{

pre->right = node;

}

pre = node;

inOrderThread(node->right, pre);

}

}

template

BTreeNode *inOrderThread(BTreeNode *node)

{

BTreeNode * pre = nullptr;

inOrderThread(node, pre);

while ((node != nullptr) && (node->left != nullptr))

{

node = node->left;

}

return node;

}

int main()

{

BTreeNode* ns = createTree();

printInOrder(ns);

cout << endl;

ns = inOrderThread(ns);

printDualList(ns);

return 0;

}

输出:

3 6 1 0 7 4 2 8 5

head -> tail:

3 6 1 0 7 4 2 8 5

tail -> head:

5 8 2 4 7 0 1 6 3

解法二:中序遍历的结点次序正好是结点的水平次序

思路

使用辅助指针,指向转换后双向链表的头结点和尾结点

根结点与左右子树转换的双向链表连接,成为完整双向链表

bVbDqmF

定义功能

inOrderThread(node, head, tail)

node: 根结点,也是中序访问的结点

head: 转换成功后指向双向链表的首结点

tail:转换成功后指向双向链表的尾结点

bVbDqmZ

编程实验:中序线索化

#include

#include "BTreeNode.h"

using namespace std;

using namespace DTLib;

template < typename T >

BTreeNode* createTree()

{

static BTreeNode ns[9];

for(int i=0; i<9; i++)

{

ns[i].value = i;

ns[i].parent = NULL;

ns[i].left = NULL;

ns[i].right = NULL;

}

ns[0].left = &ns[1];

ns[0].right = &ns[2];

ns[1].parent = &ns[0];

ns[2].parent = &ns[0];

ns[1].left = &ns[3];

ns[1].right = NULL;

ns[3].parent = &ns[1];

ns[2].left = &ns[4];

ns[2].right = &ns[5];

ns[4].parent = &ns[2];

ns[5].parent = &ns[2];

ns[3].left = NULL;

ns[3].right = &ns[6];

ns[6].parent = &ns[3];

ns[4].left = &ns[7];

ns[4].right = NULL;

ns[7].parent = &ns[4];

ns[5].left = &ns[8];

ns[5].right = NULL;

ns[8].parent = &ns[5];

return ns;

}

template < typename T >

void printInOrder(BTreeNode* node)

{

if( node != NULL )

{

printInOrder(node->left);

cout << node->value <

printInOrder(node->right);

}

}

template < typename T >

void printDualList(BTreeNode* node)

{

BTreeNode* g = node;

cout << "head -> tail: " << endl;

while( node != NULL )

{

cout << node->value << " ";

g = node;

node = node->right;

}

cout << endl;

cout << "tail -> head: " << endl;

while( g != NULL )

{

cout << g->value << " ";

g = g->left;

}

cout << endl;

}

template

void inOrderThread2(BTreeNode *node, BTreeNode *& head, BTreeNode *&tail)

{

if (node != nullptr)

{

BTreeNode *h = nullptr;

BTreeNode *t = nullptr;

inOrderThread2(node->left, h, t);

node->left = t;

if (t != nullptr)

{

t->right = node;

}

head = (h != nullptr) ? h : node;

h = nullptr;

t = nullptr;

inOrderThread2(node->right, h, t);

node->right = h;

if (h != nullptr)

{

h->left = node;

}

tail = (t != nullptr) ? t : node;

}

}

template

BTreeNode *inOrderThread2(BTreeNode *node)

{

BTreeNode *head = nullptr;

BTreeNode *tail = nullptr;

inOrderThread2(node, head, tail);

return head;

}

int main()

{

BTreeNode* ns = createTree();

printInOrder(ns);

cout << endl;

ns = inOrderThread2(ns);

printDualList(ns);

return 0;

}

输出:

3 6 1 0 7 4 2 8 5

head -> tail:

3 6 1 0 7 4 2 8 5

tail -> head:

5 8 2 4 7 0 1 6 3

以上内容整理于狄泰软件学院系列课程,请大家保护原创!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值