由于树(普通树)的结构复杂,难以以偏概全,所以在插入子树函数中书写不当,能力所限,欢迎一起交流!
树的抽象数据类型
ADT 树(Tree)
Data
树是由一个根节点和若干棵子树构成。树中结点具有相同数据类型及层次关系
Operation
InitTree(*T):构造空树
DestroyTree(*T):销毁树
CreateTree(*T,definition):按definition中给出的定义来构造树
ClearTree(*T):若树T存在,则将树T清为空树
TreeEmpty(T):若T为空树,返回true,否则返回false
TreeDepth(T):返回T的深度
Root(T):返回T的根节点
Value(T,cur_e):cur_e是树T中的一个结点,返回此节点的值
Assign(T,cur_e,value):给树T的结点cur_e赋值为value
Parent(T,cur_e):若cur_e是树T的非根节点,则返回它的双亲,否则返回空
LeftChild(T,cur_e):若cur_e是树T的非叶结点,则返回它的最左孩子,否则返回空
RightSibling(T,cur_e):若cur_e是树T的非叶结点,则返回它的右兄弟,否则返回空
InsertChild(*T,*p,i,c):其中p指向树T的某个结点,i为所指结点p的度加上1,非空树c与T不相交,操作结果为
插入c为树T中p指结点的第i棵子树
DeleteChild(*T,*p,i):其中p指向树T的某个结点,i为所指结点p的度,操作结果为删除T中p所指向结点的第i棵子树
endADT
test.hpp
#ifndef TEST_H_
#define TEST_H_
#include"malloc.h"
#include<cstdio>
#include<iostream>
#include<vector>
#define MAX_TREE_SIZE 100
typedef int TElemType;
//树的双亲表示法结点结构定义
typedef struct PTNode
{
TElemType data;
int parent;
int firstchild;
int rightsib;
};
//树结构
typedef struct
{
PTNode nodes[MAX_TREE_SIZE];
int n;//结点数
}PTree;
//InitTree(*T) :构造空树
PTree * initTree();
//DestroyTree(*T) : 销毁树
void destroyTree(PTree * T);
//CreateTree(*T, definition) : 按definition中给出的定义来构造树
void createTree(PTree * T);
//ClearTree(*T) : 若树T存在,则将树T清为空树
void clearTree(PTree * T);
//TreeEmpty(T) : 若T为空树,返回true,否则返回false
bool treeEmpty(const PTree T);
//TreeDepth(T) : 返回T的深度
int treeDepth(const PTree T);
//Root(T) : 返回T的根节点
PTNode root(const PTree T);
//Value(T, cur_e) : cur_e是树T中的一个结点,返回此节点的值
TElemType value(const PTree T, const int cur_e);
//Assign(T, cur_e, value) : 给树T的结点cur_e赋值为value
void assign(PTree * T, const int cur_e, const TElemType value);
//Parent(T, cur_e) : 若cur_e是树T的非根节点,则返回它的双亲,否则返回空
PTNode parent(const PTree T, const int cur_e);
//LeftChild(T, cur_e) : 若cur_e是树T的非叶结点,则返回它的最左孩子,否则返回空
PTNode leftChild(const PTree T, const int cur_e);
//RightChild(T, cur_e) : 若cur_e是树T的非叶结点,则返回它的右兄弟,否则返回空
PTNode rightSibling(const PTree T, const int cur_e);
//InsertChild(*T, *p, i, c) : 其中p指向树T的某个结点,i为所指结点p的度加上1,非空树c与T不相交,操作结果为
//插入c为树T中p指结点的第i棵子树
void InsertChild(PTree * T);
//DeleteChild(*T, *p, i) : 其中p指向树T的某个结点,i为所指结点p的度,操作结果为删除T中p所指向结点的第i棵子树
void deleteChild(PTree * T, const int i);
#endif // !TEST_H_
#pragma once
test.cpp
#include"test.h"
//InitTree(*T) :构造空树
PTree * initTree() {
PTree * temp = (PTree *)malloc(sizeof(PTree));
temp->n = 0;//n = 0时为空树
return temp;
}
//DestroyTree(*T) : 销毁树
void destroyTree(PTree * T) {
if (T != nullptr)
free(T);
}
//CreateTree(*T, definition) : 按definition中给出的定义来构造树
void createTree(PTree * T) {
if (T == nullptr)
return;
printf("请输入结点的个数:");
scanf("%d", &(T->n));
if (T->n > MAX_TREE_SIZE)
{
std::cerr << "结点数大于最大容量!\n";
return;
}
TElemType input;
int parentIndex;
int leftChildIndex;
int rightsiblingIndex;
for (int i = 0; i < T->n; i++)
{
getchar();
printf("请输入结点的值、双亲位于数组中的位置下标、左孩子位于数组的下标以及右兄弟位于数组的下标:");
scanf("%d %d %d %d", &input, &parentIndex,&leftChildIndex,&rightsiblingIndex);
T->nodes[i].data = input;
T->nodes[i].parent = parentIndex;
T->nodes[i].firstchild = leftChildIndex;
T->nodes[i].rightsib = rightsiblingIndex;
}
}
//ClearTree(*T) : 若树T存在,则将树T清为空树
void clearTree(PTree * T) {
if (T->n == 0)
return;
T->n = 0;
}
//TreeEmpty(T) : 若T为空树,返回true,否则返回false
bool treeEmpty(const PTree T) {
if (T.n == 0)
return true;
else
return false;
}
//TreeDepth(T) : 返回T的深度
int treeDepth(const PTree T) {
if (T.n == 0)
return 0;
//将叶节点全部找出来
std::vector<PTNode>beefNode;
for (int i = 0; i < T.n; i++)
{
if (T.nodes[i].firstchild == -1)
beefNode.push_back(T.nodes[i]);
}
//寻找叶节点所在的根节点并计数
std::vector<int>nodeDepth;
for (int i = 0; i < beefNode.size(); i++)
{
int depth = 1;
int index = beefNode[i].parent;
while (T.nodes[index].parent != -1)
{
++depth;
index = T.nodes[index].parent;
}
nodeDepth.push_back(depth);
}
//比较叶节点的最大深度即为树的深度
int maxDepth = nodeDepth[0];
for (int i = 0; i < nodeDepth.size(); i++)
{
if (maxDepth < nodeDepth[i])
maxDepth = nodeDepth[i];
}
return maxDepth + 1;
}
//Root(T) : 返回T的根节点
PTNode root(const PTree T) {
int index = T.n - 1;
PTNode temp;
while (T.nodes[index].parent != -1)
{
index = T.nodes[index].parent;
temp = T.nodes[index];
}
return temp;
}
//Value(T, cur_e) : cur_e是树T中的一个结点,返回此节点的值
TElemType value(const PTree T, const int cur_e) {
return T.nodes[cur_e - 1].data;
}
//Assign(T, cur_e, value) : 给树T的结点cur_e赋值为value
void assign(PTree * T, const int cur_e, const TElemType value) {
T->nodes[cur_e - 1].data = value;
}
//Parent(T, cur_e) : 若cur_e是树T的非根节点,则返回它的双亲,否则返回空
PTNode parent(const PTree T, const int cur_e) {
if (cur_e > T.n)
std::cerr << "树中不存在该结点\n";
else
{
if (T.nodes[cur_e - 1].parent == -1)
std::cerr << "该节点为根节点\n";
else
return T.nodes[T.nodes[cur_e - 1].parent];
}
}
//LeftChild(T, cur_e) : 若cur_e是树T的非叶结点,则返回它的最左孩子,否则返回空
PTNode leftChild(const PTree T, const int cur_e) {
if (treeDepth(T) == T.nodes[cur_e - 1].parent)
std::cerr << "该节点为叶节点\n";
else
{
if (T.nodes[cur_e - 1].firstchild == -1)
std::cerr << "该节点无左孩子\n";
else
return T.nodes[T.nodes[cur_e - 1].firstchild];
}
}
//RightChild(T, cur_e) : 若cur_e是树T的非叶结点,则返回它的右兄弟,否则返回空
PTNode rightSibling(const PTree T, const int cur_e) {
if (treeDepth(T) == T.nodes[cur_e - 1].parent)
std::cerr << "该节点为叶节点\n";
else
{
if (T.nodes[cur_e - 1].rightsib == -1)
std::cerr << "该节点无右兄弟" << std::endl;
else
return T.nodes[T.nodes[cur_e - 1].rightsib];
}
}
//InsertChild(*T, *p, i, c) : 其中p指向树T的某个结点,i为所指结点p的度加上1,非空树c与T不相交,操作结果为
//插入c为树T中p指结点的第i棵子树
void InsertChild(PTree * T) {
if (T->n + 1 > MAX_TREE_SIZE)
return;
PTNode C;
std::cout << "插入子树作为第几个结点的子树: ";
int tempNum;
std::cin >> tempNum;
C.firstchild = -1;
C.parent = tempNum;
if (T->nodes[tempNum].firstchild != -1)
{
T->nodes[tempNum].firstchild = T->n;
std::cout << "是否让插入子树为该结点的左孩子【0:否】【1:是】: ";
int istrue;
std::cin >> istrue;
if (istrue == 1)
C.rightsib = T->nodes[tempNum].firstchild;
else
{
C.rightsib = -1;
T->nodes[T->nodes[tempNum].firstchild].rightsib = tempNum;
}
}
else
{
T->nodes[tempNum].firstchild = tempNum;
C.rightsib = -1;
}
T->nodes[T->n] = C;
++T->n;
}
//DeleteChild(*T, *p, i) : 其中p指向树T的某个结点,i为所指结点p的度,操作结果为删除T中p所指向结点的第i棵子树
void deleteChild(PTree * T,const int i) {
if (T->nodes[i].firstchild != -1)
return;
if (T->nodes[i].rightsib == -1)
T->nodes[T->nodes[i].parent].firstchild = -1;
for (int j = 0; j < T->n; j++)
{
if (T->nodes[j].firstchild == i)
{
if(T->nodes[i].rightsib != -1)
T->nodes[j].firstchild = T->nodes[i].rightsib;;
}
if (T->nodes[j].rightsib == i)
{
if (T->nodes[i].rightsib != -1)
T->nodes[j].rightsib = T->nodes[i].rightsib;
}
}
}
main.cpp
#include<iostream>
#include"test.h"
void showNode(const PTNode _node);
int main()
{
PTree * T = initTree();
std::cout << "是否为空树:" << treeEmpty(*T) << std::endl;
std::cout << "树的深度为:" << treeDepth(*T) << std::endl;
createTree(T);
std::cout << "是否为空树:" << treeEmpty(*T) << std::endl;
std::cout << "树的深度为:" << treeDepth(*T) << std::endl;
PTNode rootNode = root(*T);
std::cout << "根节点为:\n";
showNode(rootNode);
std::cout << "第4个结点的值为:" << value(*T, 4) << std::endl;
PTNode parentNode10 = parent(*T, 10);
showNode(parentNode10);
PTNode parentNode1 = parent(*T, 1);
PTNode leftchild1 = leftChild(*T, 1);
showNode(leftchild1);
PTNode leftchild5 = leftChild(*T, 5);
PTNode rightsibling1 = rightSibling(*T, 1);
PTNode rightsibling7 = rightSibling(*T, 7);
showNode(rightsibling7);
return 0;
}
void showNode(const PTNode _node) {
std::cout<< "该结点的值域为:\t" << _node.data << std::endl;
std::cout << "该结点的双亲位置为:\t" << _node.parent << std::endl;
std::cout << "该结点的左孩子位置为:\t" << _node.firstchild << std::endl;
std::cout << "该结点的右兄弟位置为:\t" << _node.rightsib << std::endl;
}