二叉树:链式存储结构基础操作(C语言)

2023-11-03

操作包含:

1.二叉树的构造(先序序列和中序序列,中序序列和后序序列)

2.利用三种遍历方式输出(先序遍历,中序遍历,后序遍历,层次遍历)每种遍历包含递归和非递归两种算法。

3.栈和队列的构造(C++)模板,均为顺序存储结构


main.cpp 

1.构造二叉树。

确认中序和先序 ,或者中序和后序可以确定树的结构。

1.构造二叉树的思想:
中序可以确立某个子树的根节点的左右子树中分别的结点数,而先序和后序是用于确定结点的值。而二叉树中,从上至下,从根结点 ,确认左子树结点  右子树结点,确认左子树结点的子树的左右结点  右子树结点的左右结点……这就是递归的思想。

2.创建二叉树的思路:

建立结点,输入结点的数据。(结点数据需要在先序或者后序中找到)

找到根节点之后,根节点的左右结点也就是子树的根节点,与找整个树的根节点的思路相同,可以采用递归。

递归的尽头在于形参中的第三个数据,即结点数量。结点数量小于零时返回空。

#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
#include "queue.h"

//1.create a binary tree;
typedef struct BNode {
	char data;//data
	struct BNode*lchild;
	struct BNode*rchild;
} BTree;

void InitBTree(BTree*&b) {
	b->data = 0;
	b->lchild = b->rchild = NULL;
}

//先序序列和中序序列建立二叉树
//先序 中序 结点个数
//利用先序找到每个子树中的根节点,然后赋值*pre,in和n则是为了确立子树的位置
//利用树到子树的一般规律完成递归算法
BTree* CreateBTree1(char*pre, char* in, int n) {
	if (n <= 0) { //为空时返回空
		return NULL;
	}

	BNode *b;//结点的建立
	b = (BNode*)malloc(sizeof(BNode));
	b->data = *pre;

	char*p;//in中的*pre的类型
	for (p = in; p < in + n; p++) {
		if (*p == *pre) {
			break;
		}
	}
	int k = p - in; //k根结点的位置

	b->lchild = CreateBTree1(pre + 1, in, k); //递归左子树
	b->rchild = CreateBTree1(pre + k + 1, p + 1, n - k - 1); //递归右子树
	return b;
}

//后序和先序的不同在于根节点在最后
BTree* CreateBTree2(char *in, char *post, int n) {
	if (n <= 0) {
		return NULL;
	}

	char r = *(post + n - 1);
	BNode *b;
	b = (BNode*)malloc(sizeof(BNode));
	b->data = r;

	char*p;
	for (p = in; p < in + n; p++) {
		if (*p == r) {
			break;
		}
	}
	int k = p - in;

	b->lchild = CreateBTree2(in, post, k);
	b->rchild = CreateBTree2(p + 1, post + k, n - k - 1);
	return b;
}

2.输出二叉树,先序(递归一种,非递归两种),中序(递归一种,非递归一种),后序(递归一种,非递归一种),层次(非递归一种)

1.递归思想:每个结点都会遍历三次,差别在于在第几次遍历时输出。

非递归:见代码注释。 


//输出
//递归算法
void PreOrder1(BTree *b) {
	if (b != NULL) {
		printf("%c", b->data); //访问输出第一个结点的值
		PreOrder1(b->lchild);//遍历左子树
		PreOrder1(b->rchild);//遍历右子树
	}
}

void InOrder1(BTree *b) {
	if (b != NULL) {
		InOrder1(b->lchild);
		printf("%c", b->data);
		InOrder1(b->rchild);
	}
}

void PostOrder1(BTree *b) {
	if (b != NULL) {
		PostOrder1(b->lchild);
		PostOrder1(b->rchild);
		printf("%c", b->data);
	}
}

//非递归算法
//先序遍历
void PreOrder2(BTree *b)
//根左右,需要保存根的地址以防止丢失,可用栈保存,因为右结点先保存后用
{
	//利用栈的特点:先进后出
	//自上而下,将需要存储的直接存储
	//存储一个右节点 一个左节点 (循环)每次循环输出上次左节点时将其出栈
	BNode *p;
	stack<BTree*>s;

	if (b != NULL) {
		s.push(b);
		while (!s.empty()) {
			p = s.top();
			s.pop();
			printf("%c", p->data);

			if (p->rchild != NULL) {
				s.push(p->rchild);
			}
			if (p->lchild != NULL) {
				s.push(p->lchild);
			}
		}
		printf("\n");
	}
}

void PreOrder3(BTree *b) {
	//先存储所有左节点,然后到最底端时处理右子树,往上走出栈处理另外一层左子树的右子树
	BNode *p;
	p = b;
	stack<BTree*>s;

	while (!s.empty() || p != NULL) {
		while (p != NULL) {
			printf("%c", p->data);
			s.push(p);
			p = p->lchild;
		}

		if (!s.empty()) {
			p = s.top();
			s.pop();
			p = p->rchild;
		}
	}
	printf("\n");
}

//中序遍历
void InOrder2(BTree *b) {
	//与PreOrder3的不同是在回去的时候访问结点,为左根右
	BNode *p;
	p = b;
	stack<BTree*>s;

	while (!s.empty() || p != NULL) {
		while (p != NULL) {
			s.push(p);
			p = p->lchild;
		}

		if (!s.empty()) {
			p = s.top();
			printf("%c", p->data);
			s.pop();
			p = p->rchild;
		}
	}
	printf("\n");
}

//后序遍历
void PostOrder2(BTree *b) {
	//后序遍历和中序遍历的不同在于要将左右子树都遍历玩成后才能访问根节点并且退栈
	BTree*p, *r;
	bool flag;
	stack<BTree*>s;
	p = b;

	do {
		//将所有左结点进栈
		//将右孩子进栈
		while (p != NULL) {
			s.push(p);
			p = p->lchild;
		}

		r = NULL; //判断是否遍历过
		flag = true; //判断是否为栈顶结点

		while (!s.empty() && flag) {
			p = s.top();
			if (p->rchild == r) {//看右子树是否被遍历过
				printf("%c", p->data);
				r = s.top();
				s.pop();//遍历过就输出结点出栈
			} else {
				p = p->rchild;
				flag = false;//未遍历就退出这个循环处理右孩子
			}
		}
	} while (!s.empty());
	printf("\n");
}

//层次遍历
void LevelOrder(BTree*b) {
	BTree*p;
	queue<BTree*>q;

	q.push(b);
	while (!q.empty()) {
		p = q.front();
		q.pop();
		printf("%c", p->data);

		if (p->lchild != NULL) {
			q.push(p->lchild);
		}
		if (p->rchild != NULL) {
			q.push(p->rchild);
		}
	}
}

3.main()函数运行

int main() {
	int length = 7;

	//	char pre[10] = "ABDGCEF";
	char in[10] = "DGBAECF";
	char post[10] = "GDBEFCA";

	BTree *BT;
	//	BT = CreateBTree1(pre,in,length);
	BT = CreateBTree2(in, post, length);

	printf("先序遍历: \n" );
	PreOrder1(BT);
	printf("\n");
	PreOrder2(BT);
	PreOrder3(BT);

	printf("\n中序遍历: \n");
	InOrder1(BT);
	printf("\n");
	InOrder2(BT);

	printf("\n后序遍历: \n");
	PostOrder1(BT);
	printf("\n");
	PostOrder2(BT);

	printf("\n层次遍历: \n");
	LevelOrder(BT);

	return 0;
}

 附:queue和stack的顺序存储(模板class)

stack.h类模板 顺序存储结构

#ifndef _STACK_H_
#define _STACK_H_
#define MAX 100

template<class ElemType>
class stack {
	public:
		stack() {
			this->length = -1;
		}
		~stack() {
			delete[]this->data;
		}

		bool empty() const;
		void push(const ElemType& ET);
		void pop();
		ElemType top() const;

		ElemType* data = new ElemType[MAX];
		//top类似于线性表中的length的作用
		//线性表和栈在顺序上
		int length;
};

template<class ElemType>
bool stack<ElemType>::empty() const {
	return this->length == -1;
}

template<class ElemType>
void stack<ElemType>::push(const ElemType& ET) {
	if (this->length != MAX - 1) {
		this->data[++this->length] = ET;
	}
}

template<class ElemType>
void stack<ElemType>::pop() {
	if (this->length != -1) {
		this->length--;
	}
}

template<class ElemType>
ElemType stack<ElemType>::top() const {
	return this->data[this->length];
}

#endif

queue.h 类模板 链式存储结构

#ifndef _QUEUE_H_
#define _QUEUE_H_
#include <iostream>

template<class ElemType>
class queue {
	public:
		queue();
		~queue();

		bool empty() const;
		void push(const ElemType& e);
		void pop();
		ElemType front() const;

	private:
		struct Node {
			ElemType data;
			Node*next;

			Node(const ElemType& d, Node*n = nullptr): data(d), next(n) {};
		};

		Node*frnt;
		Node*rear;
		int size;
};

template<class ElemType>
queue<ElemType>::queue() {
	this->frnt = this->rear = nullptr;
	this->size = 0;
}

template<class ElemType>
queue<ElemType>::~queue() {
	while (this->frnt != nullptr) {
		Node*temp = this->frnt;
		this->frnt = this->frnt->next;
		delete temp;
	}
}

template<class ElemType>
bool queue<ElemType>::empty() const {
	return this->frnt == nullptr;
}

template<class ElemType>
void queue<ElemType>::push(const ElemType& e) {
	Node *newNode = new Node(e);
	if (this->empty()) {
		this->frnt = this->rear = newNode;
	} else {
		this->rear->next = newNode;
		this->rear = newNode;
	}
	this->size++;
}

template<class ElemType>
void queue<ElemType>::pop() {
	if (!this->empty()) {
		Node *temp = this->frnt;
		this->frnt = this->frnt->next;
		delete temp;
		this->size--;
	} else {
		std::cout << "queue is empty!" << std::endl;
	}
}

template<class ElemType>
ElemType queue<ElemType>::front() const {
	if (!this->empty()) {
		return this->frnt->data;
	} else
		return nullptr;
}

#endif

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二叉树:链式存储结构基础操作(C语言) 的相关文章

  • Spring概念:容器、Ioc、DI

    目录 什么是容器 什么是 IoC 传统程序的开发 理解 Spring IoC DI 总结 我们通常所说的 Spring 指的是 Spring Framework Spring 框架 它是 个开源框架 有着活跃 庞 的社区 这就是它之所以能
  • 前端知识点总结(一):从输入URL到页面展示的详细过程

    这里只是简单地概括一下大致流程 输入网址 DNS解析 建立tcp连接 客户端发送HTPP请求 服务器处理请求 服务器响应请求 浏览器展示HTML 浏览器发送请求获取其他在HTML中的资源 1 输入地址 当我们开始在浏览器中输入网址的时候 浏

随机推荐

  • 在页面中输入上下居中点号(·)

    随便打开一个聊天窗口输入汉字 点 在弹出的选项框中选择 号即可
  • dz安装好后css js位置错误,Discuz!X3.2安装后无法加载CSS/Js文件

    今天在服务器上安装了Discuz X3 2 数据库等填写正确 下一步很快就新建了291张表完成安装 没有任何报错出现 完成后访问前台和后台却无法加载CSS Js文件 F12查看它直接访问的网站根目录下边 这CSS Js文件明明不在根目录啊
  • AcWing 1293. 夏洛克和他的女朋友 二分图

    题 是一个二分图染色 质数不是质数的质因子 因为质数不会有因子 所以质数全是颜色1 合数不是合数的质因子 因为合数不 质 所以合数全都是颜色2 n小于3的时候只有1种颜色 其他都是2种颜色 include
  • 计算机网络教程_复习整理第一章

    计算机网络教程 复习整理第一章 第一章 概述 第二章 物理层 第三章 数据链路层 文章目录 计算机网络教程 复习整理第一章 1 因特网 因特网的标准制定流程 2 电路交换 报文交换 分组交换 区分三者 3 计算机网络的性能指标 lt 速率
  • d3dcompiler_43.dll缺失怎么修复

    有网友在玩游戏时出现 无法启动程序 因为计算机中丢失d3dcompiler 43 dll 尝试重新安装该程序以解决问题 的提示 那么是什么原因造成丢失d3dcompiler 43 dll呢 缺少d3dcompiler 43 dll文件怎么办
  • GLUE数据集介绍:RTE、MRPC、SST-2、QNLI、MNLI、QQP

    自然语言处理 NLP 主要包括自然语言理解 NLU 和自然语言生成 NLG 为了让NLU任务发挥最大的作用 来自纽约大学 华盛顿大学等机构创建了一个多任务的自然语言理解基准和分析平台 也就是GLUE General Language Und
  • SpringBoot注解

    使用注解的优势 1 采用纯java代码 不在需要配置繁杂的xml文件 2 在配置中也可享受面向对象带来的好处 3 类型安全对重构可以提供良好的支持 4 减少复杂配置文件的同时亦能享受到springIoC容器提供的功能 一 注解详解 配备了完
  • HIve中的查询语句

    文章目录 Hive中的查询语句 1 基础语法 2 基本查询 Select From 2 1 数据准备 0 原始数据 1 创建部门表 2 创建员工表 3 导入数据 2 2 全表和特定列查询 1 全表查询 2 选择特定列查询 2 3 列别名 1
  • kafka相关操作命令

    kafka相关操作命令 原文链接 https blog csdn net wf3612581 article details 81842574 1 开启zookeeper集群 startzk sh 2 开启kafka集群 start kaf
  • 【修电脑】VMware 从GHO文件备份恢复Win10/Win7系统

    修电脑 VMware 从GHO文件备份恢复Win10 Win7系统 注意 参考 硬盘知识 一 硬盘接口的分类 二 硬盘的分类 按照硬盘材质分为两大类 按照接口类型区分 boot启动知识 Legacy BIOS引导 uefi引导启动流程 查看
  • 区块链关键机制分析

    区块链中三大关键机制 密码算法 1 Hash算法 2 非对称加密算法 3 数字签名 存储结构 共识机制 1 工作量证明 POW 2 权益证明 POS 3 股份授权证明 DPOS 4 实用拜占庭容错 PBFT 5 Raft算法 6 Rippl
  • ubuntu18.04升级cmake

    下载cmake cmake官网 https cmake org download sudo apt get install y build essential libssl dev wget https github com Kitware
  • C++ 的 decltype 详细介绍

    1 基本介绍 decltype 是 C 11 新增的一个用来推导表达式类型的关键字 和 auto 的功能一样 用来在 编译时期 进行自动类型推导 引入 decltype 是因为 auto 并不适用于所有的自动类型推导场景 在某些特殊情况下
  • 大数据学习连载03篇:分布式技术(集群、负载、弹性、故障等知识点)

    分布式技术 一 为什么需要分布式 1 计算问题 无论是我们在学校刚开始学编程 还是在刚参加工作开始处理实际问题 写出来的程序都是很简单的 因为面对的问题很简单 以处理数据为例 可能只是把一个几十K的文件解析下 然后生成一个词频分析的报告 很
  • 怎么debug_装完机电脑点不亮怎么办?不妨看看你主板上的Debug灯

    Hello大家好 我是兼容机之家的小牛 如果你加入了一个电脑硬件爱好者的群 那么你肯定会发现一件事 那就是每天都会有小白装机点不亮在群里求助 问群问了大半天也没弄好 小牛今天来教你一个窍门 能快速判断好自己的电脑到底出了什么故障 既然你自己
  • Python实战项目:flask人脸识别图书系统(上)

    flask人脸识别图书系统 上 涉及内容 爬虫 开发 数据分析 a 前端界面的技术 gt jquery bootstrap b 后面逻辑 gt flask 前后端半分离技术 使用模块 flask 蓝图 blue print c 收集的图书数
  • Qt 5.9.7的安装及配置环境变量

    1 安装 Qt 5 9的安装跟以前的版本略有不同 选择组件时分成Qt 5 9和Tools 注意此时要勾选Qt 5 9下的MinGW 安装空间会一下增大4G左右 果断差评 不然后面通过QtCreator编译时无法添加选项 Tools下面也有一
  • AndroidKiller安装-配置-更新apktool

    下载安装好AndroidKiller后 需要对其进行配置以及更新apktool 接下来我就为大家讲解详细操作流程 1 选择配置选项 2 选择java然后配置好jdk的工程路径 切记要给到bin目录下才可以 如果是第一次打开并没有配置jdk目
  • Kamil and Making a Stream【Codeforces Round #588 (Div. 2) E】【dfs + map】

    Codeforces 1230 E 也没怎么读题 就看了下样例的note就知道了是对树上的直系祖先对子结点的链上gcd求和 然后就可以直接这样去跑一遍 个人比较的喜欢踩坑 有正着走的不走 偏偏选择了从根节点返回回来的答案 这样的做法虽然上是
  • 二叉树:链式存储结构基础操作(C语言)

    操作包含 1 二叉树的构造 先序序列和中序序列 中序序列和后序序列 2 利用三种遍历方式输出 先序遍历 中序遍历 后序遍历 层次遍历 每种遍历包含递归和非递归两种算法 3 栈和队列的构造 C 模板 均为顺序存储结构 main cpp 1 构