栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

数据结构--C++版--树的多种类别

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

数据结构--C++版--树的多种类别

数据结构-树
怎么来理解5)呢?
5)解释开始:

先来两张红黑树:

eg1:
eg2:

以eg1为例:
从34出发:一共有七条路径,每条路径都包含了两个黑色节点!

5)解释结束

以下为二叉搜索树的代码:
由两个头文件加一个.cpp文件组成

//这部分是tree.h
#include 
#include 
#include "tree.h"
#include "stack.h"



//插入根节点
bool InsertBtree(Btree** root, Bnode* node) {
	//这里定义了两个临时变量
	Bnode* tmp = NULL;
	Bnode* parent = NULL;

	if (!node) {
		return false;//先进行合法性判断,如果传进来的这个节点为空,那就不用插入了
	}
	else {//清空新节点的左右子树
		node->lchild = NULL;
		node->rchild = NULL;
	}

	if (*root) {//存在根节点 
		tmp = *root;//就把根节点放到tmp中
	}
	else {	//不存在根节点
		*root = node; //这个node直接就是根节点
		//注意:我们在main函数里,一开始定义根节点时,根节点就是空,所以,这个else{}必然会执行一次
		return true;//创建了根节点,完成任务,返回true
	}

	//此时,找到了根节点,根节点为tmp
	//要找到插入节点的父节点
	while (tmp != NULL) {

		//我们先假设这个tmp就是那个要找的父节点
		parent = tmp;//保存父节点=>此时,parent和tmp指向的位置是同一个
		printf("父节点: %dn", parent->data);

		if (isLess(node->data, tmp->data)) {//是否插入左子树,如果满足条件要插入左子树,就把tmp就指向左子树,否则就tmp就指向右子树
			//如果当前要插入的节点小于候选的父节点
			tmp = tmp->lchild;//tmp就指向左子树
		}
		else {
			tmp = tmp->rchild;//如果当前要插入的节点大于候选的父节点,tmp就指向右子树
		}
	}

	if (isLess(node->data, parent->data)) {//找到空位置后,进行插入
		parent->lchild = node;
	}
	else {
		parent->rchild = node;
	}

	return true;
}


int findMax(Btree* root)
{

	if (root->rchild == NULL) {
		return root->data;
	}
	return findMax(root->rchild);
}


Btree* DeleteNode(Btree* root, int key, Bnode*& deletedNode) {
	if (root == NULL)return NULL;

	if (root->data > key)
	{
		root->lchild = DeleteNode(root->lchild, key, deletedNode);
		return root;
	}
	if (root->data < key)
	{
		root->rchild = DeleteNode(root->rchild, key, deletedNode);
		return root;
	}

	deletedNode = root;

	//删除节点不存在左右子节点,即为叶子节点,直接删除
	if (root->lchild == NULL && root->rchild == NULL)return NULL;

	//删除节点存在右子节点,直接用右子节点取代删除节点
	if (root->lchild == NULL && root->rchild != NULL)return root->rchild;

	//删除节点存在左子节点,直接用左子节点取代删除节点
	if (root->lchild != NULL && root->rchild == NULL)return root->lchild;

	删除节点存在左右子节点,直接用左子节点最大值取代删除节点 
	int val = findMax(root->lchild);
	root->data = val;
	root->lchild = DeleteNode(root->lchild, val, deletedNode);
	return root;
}


Bnode* QueryByRec(Btree* root, ElemType e) {
	if (isEqual(root->data, e) || NULL == root) {
		return root;
	}
	else if (isLess(e, root->data)) {
		return QueryByRec(root->lchild, e);
	}
	else {
		return QueryByRec(root->rchild, e);
	}
}


Bnode* QueryByLoop(Bnode* root, int e) {
	while (NULL != root && !isEqual(root->data, e)) {
		if (isLess(e, root->data)) {
			root = root->lchild;
		}
		else {
			root = root->rchild;
		}
	}
	return root;
}

void PreOrderRec(Btree* root)
{
	if (root == NULL)
	{
		return;
	}

	printf("- %d -", root->data);
	PreOrderRec(root->lchild);
	PreOrderRec(root->rchild);
}


void PreOrder(Btree* root)
{
	Bnode cur;
	if (root == NULL)
	{
		return;
	}
	SqStack	stack; InitStack(stack);
	PushStack(stack, *root);	//头节点先入栈
	while (!(IsEmpty(stack)))	//栈为空,所有节点均已处理
	{
		PopStack(stack, cur);	//要遍历的节点 
		printf("- %d -", cur.data);

		if (cur.rchild != NULL)
		{
			PushStack(stack, *(cur.rchild));	//右子节点先入栈,后处理
		}
		if (cur.lchild != NULL)
		{
			PushStack(stack, *(cur.lchild)); //左子节点后入栈,接下来先处理
		}
	}
	DestroyStack(stack);
}

int main(void) {
	//二叉搜索树
	int test[] = { 19, 7, 25, 5, 11, 15, 21, 61 };	//二叉搜索树的原材料
	Bnode* root = NULL, * node = NULL;//先创建一个根节点和一个准备插入的节点

	node = new Bnode;//创建一个新节点
	node->data = test[0];//把新节点的数据存进去

	

	//通过插入树的接口,把新节点插入树中
	//这里&root是一个二级指针(即指针的地址)
	InsertBtree(&root, node);//插入根节点

	for (int i = 1; i < sizeof(test) / sizeof(test[0]); i++) {
		node = new Bnode;
		node->data = test[i]; if (InsertBtree(&root, node)) {
			printf("节点 %d 插入成功n", node->data);
		}
		else {

		}
	}
	printf("前序遍历结果: n"); PreOrderRec(root); printf("n");
	system("pause");


	printf("--------------------------------------------------------------------------------------n");
	

	//二叉搜索树删除 
	printf("删除节点 15n");
	Bnode* deletedNode = NULL;
	root = DeleteNode(root, 15, deletedNode);
	printf("二叉搜索树删除节点 15, %sn", deletedNode ? "删除成功" : "删除不 成功,节点不存在");
	if (deletedNode) delete deletedNode;


	printf("删除后,再次前序遍历结果: n"); PreOrderRec(root);
	printf("n");

	//二叉搜索树查找节点
	Bnode* node1 = QueryByLoop(root, 20);
	printf("搜索二叉搜索树,节点 20 %sn", node1 ? "存在" : "不存在");


	Bnode* node2 = QueryByLoop(root, 21);
	printf("搜索二叉搜索树,节点 21 %sn", node2 ? "存在" : "不存在");

	system("pause");
	return 0;
}
//这部分是tree.h
#ifndef    TREE_H 	
#define    TREE_H 	

#define  MAX_NODE 1024
#define isLess(a, b) (a 
//这部分是stack.h
#pragma once
#include
#include
#include "tree.h"
#define MaxSize	128	//预先分配空间,这个数值根据实际需要预估确定 
typedef struct _SqStack{
Bnode* base;	//栈底指针 
Bnode *top;	//栈顶指针
}SqStack;


bool InitStack(SqStack& S) //构造一个空栈 S
{
	S.base = new Bnode[MaxSize];//为顺序栈分配一个最大容量为 Maxsize 的空间
		if (!S.base) //空间分配失败 
			return false;
			S.top = S.base; //top 初始为 base,空栈 
		return true;
}


bool PushStack(SqStack& S, Bnode e) // 插入元素 e 为新的栈顶元素

{
	if (S.top - S.base == MaxSize) //栈满 return false;

		*(S.top++) = e; //元素 e 压入栈顶,然后栈顶指针加 1,等价于*S.top=e; S.top++;

	return true;
}


bool PopStack(SqStack& S, Bnode& e) //删除 S 的栈顶元素,暂存在变量 e 中

{
	if (S.base == S.top) { //栈空 return false;
	}
	e = *(--S.top); //栈顶指针减 1,将栈顶元素赋给 e

	return true;
}


Bnode* GetTop(SqStack& S) //返回 S 的栈顶元素,栈顶指针不变
{
	if (S.top != S.base) { //栈非空
		return S.top - 1; //返回栈顶元素的值,栈顶指针不变
	}
	else {
		return NULL;
	}
}

int GetSize(SqStack& S) {//返回栈中元素个数 
	return (S.top-S.base);
}

bool IsEmpty(SqStack& S) {//判断栈是否为空
	if (S.top == S.base){
	return true;
}
else {
return false;
}
}

void DestroyStack(SqStack& S) {//销毁栈
	if(S.base){
	free(S.base);

	S.base = NULL; S.top = NULL;
}
}

运行效果:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/444122.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号