二叉树链表C++实现
结点的构造

#pragma once
#ifndef NODE_H
#define NODE_H class Node
{
public:
Node();
Node *SearchNode(int nodeIndex);
void DeleteNode();
void PreorderTraversal();
void InorderTraversal();
void PostorderTraversal(); int index;
int data;
Node *pLChild;
Node *pRChild;
Node *pParent;
}; #endif // !NODE_H
需要实现的方法
#pragma once
#ifndef TREE_H
#define TREE_H
#include"Node.h"
class Tree
{
public:
Tree();//创建树
~Tree();//销毁树
Node *SearchNode(int nodeIndex);//搜索结点
bool AddNode(int nodeIndex, int direction, Node* pNode);//添加结点
bool DeleteNode(int nodeIndex, Node* pNode);//删除结点
void PreorderTraversal();//前序遍历
void InorderTraversal();//中序遍历
void PostorderTraversal();//后序遍历
private:
Node * m_pRoot;
}; #endif // ! TREE_H
创建树
申请一段内存
Tree::Tree()
{
m_pRoot = new Node();
};
创建结点
Node::Node()
{
index = ;
data = ;
pLChild = NULL;
pRChild = NULL;
pParent = NULL;
}
销毁树
调用Node的DeleteNode方法
Tree::~Tree()
{
m_pRoot->DeleteNode();
}
如果当前Node对象(this)的pLChild不为空,递归调用DeleteNode方法,this->pLChild变成了新的this,直到delete this销毁掉
如果当前Node对象(this)的pRChild不为空,递归调用DeleteNode方法,this->pRChild变成了新的this,直到delete this销毁掉
如果当前Node对象(this)的pParent不为空,如果父节点的左子节点等于当前Node对象,将当前结点置空
如果当前Node对象(this)的pParent不为空,如果父节点的右子节点等于当前Node对象,将当前结点置空
思路:指定索引向下搜索从最底层子节点开始删除,再往上回到指定索引并删除,删除的顺序是后序

void Node::DeleteNode()
{
if (this->pLChild != NULL)
{
this->pLChild->DeleteNode();
}
if (this->pRChild != NULL)
{
this->pRChild->DeleteNode();
}
if (this->pParent != NULL)
{
if (this->pParent->pLChild == this)
{
this->pParent->pLChild = NULL;
}
if (this->pParent->pRChild == this)
{
this->pParent->pRChild = NULL;
}
} delete this;
}
搜索结点
传入索引,调用Node的SearchNode方法
Node *Tree::SearchNode(int nodeIndex)
{
return m_pRoot->SearchNode(nodeIndex);
}
Node的SearchNode()
如果索引和传入索引相等,返回当前Node对象
当this对象的左子节点不为空,当左子节点索引等于传入索引,返回当前对象的子节点
否则继续对当前对象的左子节点搜索,搜索结果赋值给temp,当temp不为空,返回temp
对右子节点的逻辑同上
否则返回为空
思路:从上向下搜索,顺序为前序
Node *Node::SearchNode(int nodeIndex)
{
if (this->index == nodeIndex)
{
return this;
} Node *temp = NULL;
if (this->pLChild != NULL)
{
if (this->pLChild->index == nodeIndex)
{
return this->pLChild;
}
else
{
temp = this->pLChild->SearchNode(nodeIndex);
if (temp != NULL)
{
return temp;
}
}
} if (this->pRChild != NULL)
{
if (this->pRChild->index == nodeIndex)
{
return this->pRChild;
}
else
{
temp = this->pRChild->SearchNode(nodeIndex);
if (temp != NULL)
{
return temp;
}
}
} return NULL;
}
添加结点
传入索引,direction=0添加左子节点,direction=1添加右子节点,传入pNode参数
先搜索结点并保存在temp中,temp为空返回错误
申请内存给node,为空返回错误
将pNode的index和data分别赋值给node的index和data
node的pParent指针指向temp,temp为指定索引的父节点
direction=0,将temp的pLChild指针指向node
direction=1,将temp的pRChild指针指向node
bool Tree::AddNode(int nodeIndex, int direction, Node* pNode)
{
Node *temp = SearchNode(nodeIndex);
if (temp == NULL)
{
return false;
} Node *node = new Node();
if (node == NULL)
{
return false;
}
node->index = pNode->index;
node->data = pNode->data;
node->pParent = temp; if (direction == )
{
temp->pLChild = node;
} if (direction == )
{
temp->pRChild = node;
} return true;
}
删除结点
传入nodeIndex,pNode参数
搜索结点保存在temp
temp为空,返回错误
pNode不为空,将的temp的data赋值给pNode的data,做返回值使用
调用Node的DeleteNode方法,参见销毁树
bool Tree::DeleteNode(int nodeIndex, Node* pNode)
{
Node *temp = SearchNode(nodeIndex);
if (temp == NULL)
{
return false;
} if (pNode != NULL)
{
pNode->data = temp->data;
} temp->DeleteNode();
return true;
}
前序遍历
调用了Node的PreorderTraversal()
void Tree::PreorderTraversal()
{
m_pRoot->PreorderTraversal();
}
Node的PreorderTraversal()
先输出根节点
左子结点不为空递归,输入当前结点
右子节点不为空递归,输入当前结点
递归的算法最好对着源码打断点,就能看懂了
void Node::PreorderTraversal()
{
cout << this->index<<" "<<this->data << endl;
if (this->pLChild != NULL)
{
this->pLChild->PreorderTraversal();
}
if (this->pRChild != NULL)
{
this->pRChild->PreorderTraversal();
}
}
中序遍历和后序遍历
中序遍历:左根右
后序遍历:左右根
void Tree::InorderTraversal()
{
m_pRoot->InorderTraversal();
} void Tree::PostorderTraversal()
{
m_pRoot->PostorderTraversal();
}
逻辑与前序遍历代码相似
this->index和this->data就是根节点的内容
左右结点进行递归
void Node::InorderTraversal()
{
if (this->pLChild != NULL)
{
this->pLChild->InorderTraversal();
}
cout << this->index << " " << this->data << endl;
if (this->pRChild != NULL)
{
this->pRChild->InorderTraversal();
}
} void Node::PostorderTraversal()
{
if (this->pLChild != NULL)
{
this->pLChild->PostorderTraversal();
}
if (this->pRChild != NULL)
{
this->pRChild->PostorderTraversal();
}
cout << this->index << " " << this->data << endl;
}
补充
根据前序和中序推断出二叉的结构
前序遍历为ABDEGCFH
后序遍历为DBGEACHF

二叉树链表C++实现的更多相关文章
- 【二叉树->链表】二叉树结构转双向线性链表结构(先序遍历)
二叉树存储结构属于非线性链表结构,转化成线性链表结构,能简化操作和理解.然而由非线性转线性需要对整个树遍历一次,不同的遍历方式转化结果页不一样.下面以先序为例. 方法一: 递归法.递归遍历二叉树,因为 ...
- 二叉树、栈、队列、链表的Java代码实现
这是我的学习总结. 如有文章存在谬误,欢迎指出,有其他意见或者建议,也欢迎留言 二叉树链表 前序遍历:先访问根节点,然后访问左子树.右子树 中序遍历:先访问左子树,然后访问根节点.右子树 后序遍历:先 ...
- 二叉树3种递归和非递归遍历(Java)
import java.util.Stack; //二叉树3种递归和非递归遍历(Java) public class Traverse { /******************一二进制树的定义*** ...
- JAVA实现二叉树(简易版--实现了二叉树的各种遍历)
1,个人感觉二叉树的实现主要还是如何构造一颗二叉树.构造二叉树函数的设计方法多种多样,本例采用 addNode 方法实现.以下程序通过定义内部类来表示二叉树的结点,然后再实现了二叉树这种数据结构的一些 ...
- C#数据结构-二叉树-链式存储结构
对比上一篇文章"顺序存储二叉树",链式存储二叉树的优点是节省空间. 二叉树的性质: 1.在二叉树的第i层上至多有2i-1个节点(i>=1). 2.深度为k的二叉树至多有2k- ...
- LeetCode刷题知识点总结——二叉树
二叉树 一.二叉树理论基础 1.满二叉树:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树.通俗话理解:从底层开始到顶部的所有节点都全部填满的二叉树.深 ...
- NOIP2016初赛总结(提高组)
题目:https://www.zhihu.com/question/51865837/answer/127892121 注:我是HE的,不是JS的,照片是ZYJ神犇的 单选 一.单项选择题(共15 题 ...
- Java中二叉树存储结构实现
一.二叉树 二叉树指的是每个节点最多只能有两个子树的有序树.通常左边的子树被称为“左子树”(left subtree),右边的子树被称为右子树. 二叉树的每个节点最多只有2棵子树,二叉树的子树次序不能 ...
- 2017-2018-1 20179205《Linux内核原理与设计》第四周作业
<Linux内核原理与分析> 视频学习及实验操作 Linux内核源代码 视频中提到了三个我们要重点专注的目录下的代码,一个是arch目录下的x86,支持不同cpu体系架构的源代码:第二个是 ...
随机推荐
- .net core i上 K8S(七).netcore程序的服务发现
上一章我们分享了k8s的网络代理模式,今天我们来分享一下k8s中的服务发现. 1.环境变量模式的服务发现 k8s默认为我们提供了通过环境变量来实现服务发现的功能,前提是 1.需要service在pod ...
- Adorner 装饰器
装饰器 Adorner 装饰器是WPF中较为常用的技术之一,也是不同于XAML的技术. 较为特殊. 特殊于装饰器全部由C#构成,不同于ControlTenmpate和Style的元素. 装饰器在某些方 ...
- centos7 修改网卡eth0 关闭ipv6 问题总结
1. 首先关闭"NetworkManager" 服务. 然后编辑网卡的配置文件将里面的NAME DEVICE项修改为eth0 vim /etc/sysconfig/network- ...
- css3箭头
<!DOCTYPE html> <html lang="en" class="muui-theme-webapp-main"> < ...
- 编程开发之--Java集合类继承与实现必备知识
1.LinkedHashSet有序链式集合 举例: long startTime=System.currentTimeMillis(); LinkedHashSet oprTypeSet = new ...
- APP元素的四大类
一个完整的APP包括四大类:各种“栏”.内容视图.控制元素.临时视图 各种“栏”:状态栏.导航栏.标签栏.工具栏.范围栏 内容视图:列表视图.卡片式图.集合视图.图片视图.文本视图 控制元素:用于控制 ...
- Angular material mat-icon 资源参考_Warning
ul,li>ol { margin-bottom: 0 } dt { font-weight: 700 } dd { margin: 0 1.5em 1.5em } img { height: ...
- Pytorch学习笔记(二)——Tensor
一.对Tensor的操作 从接口的角度讲,对Tensor的操作可以分为两类: (1)torch.function (2)tensor.function 比如torch.sum(a, b)实际上和a.s ...
- Python3.0版本 从听说python可以做爬虫到自己第一成功做出爬虫的经历
前言 我自己是个python小白,工作也不是软件行业,但是日常没事时喜欢捣鼓一些小玩意,自身有点C语言基础. 听说python很火,可以做出爬虫去爬一些数据图片视频之类的东东,我的兴趣一下子就来了.然 ...
- adb的常用命令及如何查看被占用的端口
adb是什么?:adb的全称为Android Debug Bridge,就是起到调试桥的作用.通过adb我们可以在Eclipse中方面通过DDMS来调试Android程序,说白了就是debug工具.a ...