IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 数据结构——二叉树 -> 正文阅读

[数据结构与算法]数据结构——二叉树

?

1.顺序存储

?

根节点位序为0。剩下的结点,假设位序为i,如果左孩子存在,左孩子为2i+1。

如果右孩子存在,右孩子为2i+2。其父节点都为(i-1)/2。

如果结点不存在,可以用一个数来标记。

缺点是容易造成空间浪费,一般用于完全二叉树,或者接近完全二叉树的二叉树存储。

?2.链式存储结构

链式存储有两种链表结点,一种是二叉链表结点,另一种是三叉链表结点。

二叉链表结点仅存储左右孩子的指针和该结点的数据。

而三叉链表结点多加了一个指向双亲结点的指针。

这两个结点当然也可以用于顺序存储。

仅谈二叉链表:

1.深度优先遍历?

(1)前序遍历(DLR即data、left、right)

? ? ? ? 可以看出,当该结点不为空,先遍历该结点,然后遍历左节点,再遍历右节点,最后结束。

? ? ? ? 否则返回,直到所有节点完成遍历。

(2)中序遍历(LDR)

????????可以看出,当该结点不为空,先遍历该结点的左节点,然后遍历该节点,再遍历该节点的右? ? ? ? ? ? 节点,最后结束。

? ? ? ? 否则返回,直到所有节点完成遍历。

(3)后序遍历(LRD)

????????可以看出,当该结点不为空,先遍历该结点的左节点,然后遍历该节点的右节点,然后遍历? ? ? ? ? ? 该节点,最后结束。

? ? ? ? 否则返回,直到所有节点完成遍历。

记忆的话,就是该结点遍历顺序在哪,就是什么序遍历。并且按照左节点在右节点之前的遍历。

2.广度优先遍历

????????层序遍历:

????????

? ? ? ? ?即先从上到下,从左到右,如图中数字顺序遍历。

#pragma once
#include<stack>
#include<queue>
#include<iostream>
template<class T>
class binary_tree
{
public:
	struct node
	{
		T data;
		node* left;
		node* right;
		node() = default;
		node(const T& d, node* const l = nullptr, node* const r = nullptr)
		{
			data = d; left = l; right = r;
		}
	};
	node* root;
	binary_tree():root(nullptr){}
	~binary_tree() { p_clear(root); }
	unsigned size() { return p_size(root); }
	unsigned height() { return p_height(root); }
	unsigned leaf_num() { return p_leaf_num(root); }
	void preorder0() { p_preorder0(root); }
	void preorder1() { p_preorder1(root); }
	void inorder0() { p_inorder0(root); }
	void inorder1() { p_inorder1(root); }
	void postorder0() { p_postorder0(root); }
	void postorder1() { p_postorder1(root); }
	void levelorder() { p_levelorder(root); }
private:
	//名字前面有个p表示私有private
	unsigned p_size(node* root);//求结点数
	void p_clear(node* root);//删除所有结点
	unsigned p_height(node* root);//求二叉树高度
	unsigned p_leaf_num(node* root);//求二叉树叶子结点个数
	//1表示递归方式,0表示非递归方式
	void p_preorder0(node* root);//前序遍历
	void p_preorder1(node* root);
	void p_inorder0(node* root);//中序遍历
	void p_inorder1(node* root);
	void p_postorder0(node* root);
	void p_postorder1(node* root);//后序遍历
	void p_levelorder(node* root);
};
template<class T>
unsigned binary_tree<T>::p_size(node* root)
{
	//如果当前结点为空,返回0
	if (!root)
		return 0;
	//如果非空,结点数等于1(表示当前结点)+左子树结点数+右子树结点数
	return 1 + p_size(root->left) + p_size(root->right);
}
template<class T>
void binary_tree<T>::p_clear(node* root)
{
	if (!root)//结点为空就返回
		return;
	else
	{
		node* p = root;
		p_clear(p->left);//删除左子树
		p_clear(p->right);//删除右子树
		delete p;//删除当前结点
	}
}
template<class T>
unsigned binary_tree<T>::p_height(node* root)
{
	if (!root)
		return 0;
	unsigned left_height = p_height(root->left);//左子树长度
	unsigned right_height = p_height(root->right);//右子树长度
	return 1 + (left_height >= right_height ? left_height : right_height);
}
template<class T>
unsigned binary_tree<T>::p_leaf_num(node* root)
{
	//如果是叶子结点,返回1
	if (!root->left&&!root->right)
		return 1;
	//如果不是的话,返回左子树叶子结点+右子树叶子结点
	return p_leaf_num(root->left) + p_leaf_num(root->right);
}
template<class T>
void binary_tree<T>::p_preorder0(node* root)
{
	if (!root)
		return;
	//不递归,采用栈结构
	std::stack<node*> obj;
	/*两种方法
	* Node* p=root;
	* while(!obj.empty()||p)
	* {
	*	if(p)//存在即先遍历当前结点,将当前压入栈,留待以后访问右节点,然后遍历左节点
	*	{
	*		std::cout<<p->data<<" ";
	*		obj.push(p);
	*		p=p->left;
	*	}
	*	else//左节点访问到头,访问上一个结点的右节点,
	*	{
	*		p=obj.top();
	*		obj.pop();
	*		p=p->right;
	*	}
	* }
	*/
	//优化一下
	obj.push(root);
	while (!obj.empty())
	{
		auto p = obj.top();
		obj.pop();
		std::cout << p->data << " ";
		//先压右结点,后压左节点,保证下一次访问该结点的左节点
		if(p->left)
			obj.push(p->right);
		if(p->right)
			obj.push(p->left);
	}
	return;
}
template<class T>
void binary_tree<T>::p_preorder1(node* root)
{
	if (!root)
		return;
	std::cout << root->data << " ";
	p_preorder1(root->left);//访问左节点
	p_preorder1(root->right);//访问右节点
}
template<class T>
void binary_tree<T>::p_inorder0(node* root)
{
	if (!root)
		return;
	std::stack<node*> obj;
	auto p = root;
	while (!obj.empty() || p)
	{
		if (p)//将该结点压入栈内,留待以后遍历
		{
			obj.push(p);
			p = p->left;
		}
		else
		{
			p = obj.top();
			obj.pop();
			std::cout << p->data << " ";
			p = p->right;
		}
	}
}
template<class T>
void binary_tree<T>::p_inorder1(node* root)
{
	if (root->left)//有左孩子
		p_inorder1(root->left);
	std::cout << root->data << " ";
	if (root->right)
		p_inorder1(root->right);
}
template<class T>
void binary_tree<T>::p_postorder0(node* root)
{
	enum child_type{Left,Right};
	struct elem
	{
		node* pointer;
		child_type flag;
	};
	std::stack<elem> obj;
	auto p = root;
	elem q;
	while (!obj.empty() || p)
	{
		if (p)
		{
			q.pointer = p;
			q.flag = Left;
			obj.push(q);
			p = p->left;
		}
		else
		{
			q = obj.top();
			obj.pop();
			p = q.pointer;
			if (q.flag==Left)//从左边回来且有右孩子
			{
				q.flag = Right;
				obj.push(q);
				p = p->right;
			}
			else
			{
				std::cout << p->data << " ";
				p = nullptr;
			}
		}
	}
}
template<class T>
void binary_tree<T>::p_postorder1(node* root)
{
	if (root->left)
		p_postorder1(root->left);
	if (root->right)
		p_postorder1(root->right);
	std::cout << root->data << " ";
}
template<class T>
void binary_tree<T>::p_levelorder(node* root)
{
	std::queue<node*> obj;
	obj.push(root);
	while (!obj.empty())
	{
		int sum = obj.size();
		while (sum--)
		{
			auto p = obj.front();
			obj.pop();
			std::cout << p->data << " ";
			if (p->left)
				obj.push(p->left);
			if (p->right)
				obj.push(p->right);
		}
	}
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-05 11:44:27  更:2022-05-05 11:49:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:42:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码