70、二叉树题目

单度结点删除:

编写一个函数用于删除单度结点,删除后,其唯一的子节点替代它的位置。

结点包含指向父结点的指针:

定义功能:delOdd1(node)

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

delOdd1(node)=

return; node==NULL

parent=node->parent;parent->child=node->child;node->child->parent=parent;delOdd1(node->child); degree==1

delOdd1(node->left);delOdd1(node->right); degree==0or degree==2

结点中只包含左右孩子指针

定义功能:delOdd2(node) //node为结点指针的引用

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

delOdd2(node)=

return ; node==NULL

node=node->child;delOdd(node); degree==1

delOdd2(node->left);delOdd2(node->right);degree==0 or degree==2

#include <iostream>
#include "BTree.h"
#include "BTreeNode.h"
#include "WSstring.h"
using namespace std;
using namespace WSlib;
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>
BTreeNode<T>* delOdd1(BTreeNode<T>* node)
{
BTreeNode<T>* ret=NULL;
if(node!=NULL)
{
if(((node->left!=NULL)&&(node->right==NULL))||((node->left==NULL)&&(node->right!=NULL)))
{
BTreeNode<T>* parent=dynamic_cast<BTreeNode<T>*>(node->parent);
BTreeNode<T>* node_child=(node->left!=NULL)? node->left:node->right;
if(parent !=NULL) //根结点可能单度,那么他的parent就是空
{
BTreeNode<T>*& parent_child=(parent->left==node)?parent->left:parent->right;
parent_child=node_child;
node_child->parent=parent;
}
else
{
node_child->parent=NULL;//子孩子的父亲为空,node_child与parent断开
}
if(node->flag())
{
delete node;
}
ret=delOdd1(node_child);
}
else
{
delOdd1(node->left);
delOdd1(node->right);
ret=node;
}
}
return ret;
}
//删除只有左右孩子的单度结点
template <typename T>
void delOdd2(BTreeNode<T>*& node)//node 是c++引用
{
if(node!=NULL)
{
if(((node->left!=NULL)&&(node->right==NULL))||((node->left==NULL)&&(node->right!=NULL)))
{
BTreeNode<T>* node_child=(node->left!=NULL)?node->left:node->right;
if(node->flag())
{
delete node;
}
node=node_child;//node父结点中孩子的别名?老师这样讲,但是我感觉还是父结点,改动指针的引用就改了孩子?孩子的孩子复制给父亲的子指针。孩子的孩子复制给父亲的子指针。node不是一个指针,而是父结点中孩子指针的引用,而不是指向了孩子。引用与指针的区别,一个是就把孩子的指针复制给他,另一个是,引用了这个指针
delOdd2(node);
}
else
{
delOdd2(node->left);
delOdd2(node->right);
}
}
}
int main()
{
BTreeNode<int>* ns=createTree<int>();
printInOrder(ns);
cout<<endl;
//ns=delOdd1(ns);
delOdd2(ns);
printInOrder(ns);
cout<<endl;
/*带父指针的测试
int a[]={6,7,8};//验证parent指针处理好没
for(int i=0;i<3;i++)
{
TreeNode<int>* n=ns+a[i];//n代表叶节点
while(n!=NULL)
{
cout<<n->value<<" ";
n=n->parent;


}
cout<<endl;


}
cout<<endl;*/
return 0;
}

2题:中序线索化二叉树:编写一个函数用于中序线索化二叉树,不允许使用其他数据结构。

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

思路:使用辅助指针,在中序遍历时指向当前结点的前驱结点,访问当前结点时,连接与前驱结点的先后次序。

定义功能:inOrderThread(node,pre)

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

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

inOrderThread(node,pre)=

return; node==NULL

inOrderThread(node->left,pre);node->left=pre;pre->right=node;pre=node;inOrderThread(node->right,pre); node!=NULL

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

思路:使用辅助指针,指向转换后双向链表的头结点和尾节点,根结点与左右子树转换的双向链表连接,成为完整双向链表。

定义功能:inOrderThread(node,head,tail)

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

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

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

inOrderThread(node,head,pre)=

return; node==NULL

inOrderThread(node->left,h,t);node->left=t;t->right=node;inOrderThread(node->right,h,t);node->right=h;h->left=node; node!=NULL

template <typename T>
void inOrderThread(BTreeNode<T>* node,BTreeNode<T>*& head,BTreeNode<T>*& tail)
{
if(node!=NULL)
{
BTreeNode<T>* h=NULL;
BTreeNode<T>* t=NULL;
inOrderThread(node->left,h,t);
node->left=t;
if(t!=NULL)
{
t->right=node;
}
head= (h !=NULL)? h:node;
h=NULL; //左子树遍历完要h,t赋值为空,要不然出错
t=NULL;
inOrderThread(node->right,h,t);
node->right=h;
if(h!=NULL)
{
h->left=node;
}
tail=(t!=NULL)? t:node;
}
}
template <typename T>
BTreeNode<T>* inOrderThread2(BTreeNode<T>* node)
{
BTreeNode<T>* head=NULL;
BTreeNode<T>* tail=NULL;
inOrderThread(node,head,tail);
return head;

}

ns=inOrderThread2(ns);// main中
printDualList(ns);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值