树(普通树)的C代码实现

由于树(普通树)的结构复杂,难以以偏概全,所以在插入子树函数中书写不当,能力所限,欢迎一起交流!

树的抽象数据类型
	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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值