面试题 一
单结点删除
描述:编写一个函数用于删除二叉树中的所有单度结点
要求:结点删除后,其唯一的子结点替代它的位置
情形1:结点中包含指向父结点的指针
定义功能:delOdd1(node)
- 删除 node 为根结点的二叉树中的单度结点
编程实验:单度结点的删除
#include <iostream>
#include "BTreeNode.h"
using namespace std;
using namespace DTLib;
template < typename T >
BTreeNode<T>* createTree()
{
static BTreeNode<int> 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<T>* node)
{
if( node != NULL )
{
printInOrder(node->left);
cout << node->value <<" ";
printInOrder(node->right);
}
}
template < typename T >
void printDualList(BTreeNode<T>* node)
{
BTreeNode<T>* 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 <typename T>
BTreeNode<T>* delOdd1(BTreeNode<T> *node)
{
BTreeNode<T> *ret = nullptr;
if (node != nullptr)
{
if (((node->left != nullptr) && (node->right == nullptr)) ||
((node->left == nullptr) && (node->right != nullptr)))
{
BTreeNode<T> *parent = dynamic_cast<BTreeNode<T>*>(node->parent);
BTreeNode<T> *child = (node->left != nullptr) ? node->left : node->right;
if (parent != nullptr)
{
BTreeNode<T> *& 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<int>* ns = createTree<int>();
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 为根结点的二叉树中的单度结点
编程实验:单度结点删除
#include <iostream>
#include "BTreeNode.h"
using namespace std;
using namespace DTLib;
template < typename T >
BTreeNode<T>* createTree()
{
static BTreeNode<int> 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<T>* node)
{
if( node != NULL )
{
printInOrder(node->left);
cout << node->value <<" ";
printInOrder(node->right);
}
}
template < typename T >
void printDualList(BTreeNode<T>* node)
{
BTreeNode<T>* 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 <typename T>
void delOdd2(BTreeNode<T> *&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<int>* ns = createTree<int>();
printInOrder(ns);
cout << endl;
delOdd2(ns);
printInOrder(ns);
return 0;
}
输出:
3 6 1 0 7 4 2 8 5
6 0 7 2 8
面试题 二
中序线索化二叉树
描述:编写一个函数用于中序线索化二叉树
要求:不允许使用其他数据结构
解法一:在中序遍历的同时进行线索化
思路
- 使用辅助指针,在中序遍历时指向当前结点的前驱结点
- 访问当前结点时,连接与前驱结点的先后次序
定义功能
inOrderThread(node, pre)
- node : 根结点,也是中序访问的结点
- pre: 为中序遍历时的前驱结点指针
编程实验:中序线索化
#include <iostream>
#include "BTreeNode.h"
using namespace std;
using namespace DTLib;
template < typename T >
BTreeNode<T>* createTree()
{
static BTreeNode<int> 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<T>* node)
{
if( node != NULL )
{
printInOrder(node->left);
cout << node->value <<" ";
printInOrder(node->right);
}
}
template < typename T >
void printDualList(BTreeNode<T>* node)
{
BTreeNode<T>* 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 <typename T>
void inOrderThread(BTreeNode<T> *node, BTreeNode<T> *&pre)
{
if (node != nullptr)
{
inOrderThread(node->left, pre);
node->left = pre;
if (pre != nullptr)
{
pre->right = node;
}
pre = node;
inOrderThread(node->right, pre);
}
}
template <typename T>
BTreeNode<T> *inOrderThread(BTreeNode<T> *node)
{
BTreeNode<T> * pre = nullptr;
inOrderThread(node, pre);
while ((node != nullptr) && (node->left != nullptr))
{
node = node->left;
}
return node;
}
int main()
{
BTreeNode<int>* ns = createTree<int>();
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
解法二:中序遍历的结点次序正好是结点的水平次序
思路
- 使用辅助指针,指向转换后双向链表的头结点和尾结点
- 根结点与左右子树转换的双向链表连接,成为完整双向链表
定义功能
inOrderThread(node, head, tail)
- node: 根结点,也是中序访问的结点
- head: 转换成功后指向双向链表的首结点
- tail:转换成功后指向双向链表的尾结点
编程实验:中序线索化
#include <iostream>
#include "BTreeNode.h"
using namespace std;
using namespace DTLib;
template < typename T >
BTreeNode<T>* createTree()
{
static BTreeNode<int> 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<T>* node)
{
if( node != NULL )
{
printInOrder(node->left);
cout << node->value <<" ";
printInOrder(node->right);
}
}
template < typename T >
void printDualList(BTreeNode<T>* node)
{
BTreeNode<T>* 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 <typename T>
void inOrderThread2(BTreeNode<T> *node, BTreeNode<T> *& head, BTreeNode<T> *&tail)
{
if (node != nullptr)
{
BTreeNode<T> *h = nullptr;
BTreeNode<T> *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 <typename T>
BTreeNode<T> *inOrderThread2(BTreeNode<T> *node)
{
BTreeNode<T> *head = nullptr;
BTreeNode<T> *tail = nullptr;
inOrderThread2(node, head, tail);
return head;
}
int main()
{
BTreeNode<int>* ns = createTree<int>();
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
以上内容整理于狄泰软件学院系列课程,请大家保护原创!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。