数据结构--二叉树 Binary Tree

文章目录

    • 1.概念
    • 2.存储方式
      • 2.1 链式存储(二叉树代码大部分是链式实现的)
      • 2.2 顺序存储(基于数组)
    • 3.二叉树的遍历
      • 3.1 基于链表的二叉树实现代码
      • 3.2 基于数组的二叉树实现代码
      • 3.3 非递归法 二叉树遍历

在这里插入图片描述

1.概念

  • 二叉树,每个节点最多有两个“叉”,也就是两个子节点,分别是左子节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点
  • 满二又树,叶子节点全都在最底层,除了叶子节点之外,每个节点都有左右两个子节点。
  • 完全二叉树,叶子节点都在最底下两层,最后一层的叶子节点都靠排列,并且除了最后一层,其他层的节点个数都要达到最大。

在这里插入图片描述
在这里插入图片描述

2.存储方式

2.1 链式存储(二叉树代码大部分是链式实现的)

在这里插入图片描述

2.2 顺序存储(基于数组)

  • 根节点存储在下标 i = 1 的位置,那左子节点存储在下标 2 * i = 2 的位置,右子节点存储在 2 * i + 1 = 3 的位置。
  • 以此类推,B节点的左子节点存储在 2 * i = 2 * 2 = 4 的位置,右子节点存储在 2 * i + 1 = 2 * 2 + 1 = 5 的位置。
    在这里插入图片描述
    堆排序中的堆就是完全二叉树。
    在这里插入图片描述

3.二叉树的遍历

在这里插入图片描述

void preOrder(Node* root)
{if(root==NULL)return;print root;				//打印root节点preOrder(root->1eft);preOrder(root->right);
}
void inorder(Node* root)
{if(root==NULL)return;inorder(root->1eft);print root;				//打印root节点inorder(root->right);
}
void postorder(Node* root)
{if(root==NULL)return;postorder(root->1eft);postorder(root->right);print root;				//打印root节点
}
void levelorder(Node* root)	//按层从左至右打印
{if(root==NULL)return;queue<node*> nodeQueuenodequeue.push(root);while(!nodequeue.empty())   //建立节点队列,打印父节点,入队左右子节点,出队父节点{node* p = nodeQueue.front();cout << p->data << " ";if(p->left != NULL)nodeQueue.push(p->left);if(p->right != NULL)nodeQueue.push(p->right);nodeQueue.pop();}
}

每个节点最多会被访问 2 次, 所以遍历操作的时间复杂度, 跟节点的个数 n 成正比,二叉树遍历的时间复杂度是 O(n)

3.1 基于链表的二叉树实现代码

/*** @description: 二叉树,链表实现* @author: michael ming* @date: 2019/5/11 18:03* @modified by: */
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
template <class T>
struct node
{T data;node<T> *left, *right;node<T>():left(NULL), right(NULL){}
};
template <class T>
class binary_tree
{
private:int nodelen;node<T> *root;
public:binary_tree():nodelen(0), root(NULL){}node<T>* getRoot()const{return root;}node<T>* insert(node<T> * nodep, size_t lv, size_t toplv, int data = 1){if(lv == 0)return NULL;else if(nodep == NULL && lv == toplv){root = new node<T>();nodep = root;}else{nodep = new node<T>();}nodep->data = data;nodelen++;node<T>* l = insert(nodep->left, lv-1, toplv, 2*data);if(l)nodep->left = l;    //返回创建好的left节点l,跟父接上node<T>* r = insert(nodep->right, lv-1, toplv, 2*data+1);if(r)nodep->right = r;   //返回创建好的right节点r,跟父接上return nodep;}void preOrderPrint(node<T> * nodep){if (nodep == NULL)return;cout << nodep->data << " ";preOrderPrint(nodep->left);preOrderPrint(nodep->right);}void inOrderPrint(node<T> * nodep){if (nodep == NULL)return;inOrderPrint(nodep->left);cout << nodep->data << " ";inOrderPrint(nodep->right);}void postOrderPrint(node<T> * nodep){if (nodep == NULL)return;postOrderPrint(nodep->left);postOrderPrint(nodep->right);cout << nodep->data << " ";}void levelOrderPrint(node<T> * nodep)    //按层打印{if (nodep == NULL)return;queue<node<T>*> nodequeue;nodequeue.push(nodep);while(!nodequeue.empty())   //建立节点队列,打印父节点,入队左右子节点,出队父节点{node<T>* p = nodequeue.front();cout << p->data << " ";if(p->left != NULL)nodequeue.push(p->left);if(p->right != NULL)nodequeue.push(p->right);nodequeue.pop();}}void destory_tree(node<T> * nodep){if (nodep == NULL)return;destory_tree(nodep->left);destory_tree(nodep->right);delete nodep;}//-----------------求二叉树高度-----------------------int get_height(node<T>* nodep)  //递归法, 求左右子树高度,较大的+1{if(nodep == NULL)return 0;int leftheight = get_height(nodep->left);int rightheight = get_height(nodep->right);return max(leftheight, rightheight) + 1;}int level_get_height(node<T>* nodep)    //按层计算高度{if (nodep == NULL)return 0;queue<node<T>*> nodequeue;node<T>* p = NULL;nodequeue.push(nodep);int height = 0;while(!nodequeue.empty())   //建立节点队列,入队左右子节点,出队父节点{height++;int n = nodequeue.size();for(int i = 0; i < n; ++i){p = nodequeue.front();if(p->left != NULL)nodequeue.push(p->left);if(p->right != NULL)nodequeue.push(p->right);nodequeue.pop();}}return height;}int stack_get_height(node<T>* nodep)    //用栈实现前序(或后序)遍历,最大栈长度即为树的高度{if (nodep == NULL)return 0;stack<node<T>*> nodestack;node<T> *temp = NULL;int height = 0;while(nodep != NULL || !nodestack.empty()){if(nodep != NULL){nodestack.push(nodep);nodep = nodep->left;//找到最底端左节点}else{nodep = nodestack.top();//最底端左节点的父节点nodepif(nodep->right != NULL && nodep->right != temp)   //右边有节点,且没有进过栈nodep = nodep->right;   //进入右节点,跳到上个if查其子树else    //没有子节点,或者子节点进过栈{if(nodestack.size() > height)height = nodestack.size();  //更新最大高度temp = nodep;   //记录弹栈的节点到tempnodestack.pop();nodep = NULL;}}}return height;}
};int main()
{binary_tree<int> btree;btree.insert(btree.getRoot(), 3, 3);btree.preOrderPrint(btree.getRoot());cout << endl << endl;btree.inOrderPrint(btree.getRoot());cout << endl << endl;btree.postOrderPrint(btree.getRoot());cout << endl << endl;btree.levelOrderPrint(btree.getRoot());cout << endl;cout << "height of tree: " << btree.get_height(btree.getRoot()) << endl;cout << "level height of tree: " << btree.level_get_height(btree.getRoot()) << endl;cout << "stack height of tree: " << btree.stack_get_height(btree.getRoot()) << endl;btree.destory_tree(btree.getRoot());return 0;
}

在这里插入图片描述
在这里插入图片描述

3.2 基于数组的二叉树实现代码

/*** @description: 二叉树,数组实现* @author: michael ming* @date: 2019/5/11 11:44* @modified by: */
#include <iostream>
using namespace std;
template <class T>
struct node
{T data;node<T>(){}
};
template <class T>
class binary_tree
{
private:int size;size_t tree_arrlen;node<T>* tree;
public:binary_tree(int len = 20):size(len),tree_arrlen(0){tree = new node<T> [size];}~binary_tree(){delete [] tree;}void insert(T &data){if(tree_arrlen < size)tree[++tree_arrlen].data = data;}void preOrderPrint(size_t index = 1){if(tree_arrlen < 1 || index > tree_arrlen)return;cout << tree[index].data << " ";preOrderPrint(index*2);preOrderPrint(index*2+1);}void inOrderPrint(size_t index = 1){if(tree_arrlen < 1 || index > tree_arrlen)return;inOrderPrint(index*2);cout << tree[index].data << " ";inOrderPrint(index*2+1);}void postOrderPrint(size_t index = 1){if(tree_arrlen < 1 || index > tree_arrlen)return;postOrderPrint(index*2);postOrderPrint(index*2+1);cout << tree[index].data << " ";}
};int main()
{binary_tree<int> btree;for(int i = 1; i < 8; ++i)btree.insert(i);btree.preOrderPrint();cout << endl;btree.inOrderPrint();cout << endl;btree.postOrderPrint();return 0;
}

在这里插入图片描述

3.3 非递归法 二叉树遍历

  • 前序(入栈root,访问stack.top(), 出栈,依次入栈节点,节点)
void stackPreOrder()
{stack<node<T>*> nodeStack;node<T> * nodep = root;if(nodep != NULL){nodeStack.push(nodep);while(!nodeStack.empty()){nodep = nodeStack.top();nodeStack.pop();cout << nodep->data << " ";if(nodep->right != NULL)    //注意左右节点入栈顺序!!!nodeStack.push(nodep->right);if(nodep->left != NULL)nodeStack.push(nodep->left);}}
}
  • 中序(入栈右、根、(左的右、左的根、…),左右节点为空,到达叶子节点,打印叶子节点,)
void stackInOrder()
{stack<node<T>*> nodeStack;node<T> *nodep = root;while(nodep != NULL){while(nodep != NULL)//入栈右、根{if(nodep->right)nodeStack.push(nodep->right);nodeStack.push(nodep);nodep = nodep->left;}nodep = nodeStack.top();//根节点nodeStack.pop();while(!nodeStack.empty() && nodep->right == NULL)//nodep为叶子节点{cout << nodep->data << " ";//打印叶子节点nodep = nodeStack.top();nodeStack.pop();}cout << nodep->data << " ";//左节点为空,右节点非空or最后一个节点if(!nodeStack.empty()){nodep = nodeStack.top();nodeStack.pop();}elsenodep = NULL;}
}
  • 后序
void stackPostOrder()
{stack<node<T>*> nodeStack;node<T> *nodep = root, *temp = root;while(nodep != NULL){for(;nodep->left != NULL; nodep = nodep->left)nodeStack.push(nodep);  //入栈一路上的左节点while(nodep->right == NULL || nodep->right == temp){cout << nodep->data << " ";//打印叶子节点temp = nodep;if(nodeStack.empty())return;nodep = nodeStack.top();//回到父节点nodeStack.pop();}nodeStack.push(nodep);nodep = nodep->right;//转到右子树}
}

完整代码
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/480304.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法工程师思维导图—数据结构与算法

卖萌屋的妹子们&#xff08;划掉&#xff09;作者团整理的算法工程师思维导图&#xff0c;求职/自我提升/查漏补缺神器。该手册一共分为数据结构与算法、数学基础、统计机器学习和深度学习四个部分。点击这里查看具体使用指南。该手册有两种获取方式&#xff1a;公众号后台回复…

通过预训练提升语言理解

官方地址&#xff1a;https://blog.openai.com/language-unsupervised/文章&#xff1a;https://s3-us-west-2.amazonaws.com/openai-assets/research-covers/language-unsupervised/language_understanding_paper.pdf代码&#xff1a;https://github.com/openai/finetune-tran…

最全Java架构师130面试题:微服务、高并发、大数据、缓存等中间件

一、数据结构与算法基础 说一下几种常见的排序算法和分别的复杂度。 用Java写一个冒泡排序算法 描述一下链式存储结构。 如何遍历一棵二叉树&#xff1f; 倒排一个LinkedList。 用Java写一个递归遍历目录下面的所有文件。 二、Java基础 接口与抽象类的区别&#xf…

智能投顾全面解读

智能投顾全面解读 <p>传统投顾一直是与理财产品的销售紧密结合在一起的。投顾即销售&#xff0c;在国内理财界也是约定俗成的现实。<br></p><p>传统投资顾问即证券投资顾问业务遵循《证券投资顾问业务暂行规定》&#xff0c;开展证券投资顾问业务的机构…

数据结构--二叉查找树 Binary Search Tree

文章目录1.二叉查找树概念2.二叉查找树操作2.1 查找2.2 插入2.3 删除2.4 其他3. 支持重复数据的二叉查找树4 有散列表了&#xff0c;还需要二叉查找树&#xff1f;5 代码实现1.二叉查找树概念 二叉查找树要求&#xff0c;在树中的任意一个节点&#xff0c;其左子树中的每个节点…

最新蚂蚁金服Java面试题:Docker+秒杀设计+RocketMQ+亿级数据设计

蚂蚁金服一面&#xff1a; 1 自我介绍 2 讲一下ArrayList和linkedlist的区别&#xff0c;ArrayList的扩容方式&#xff0c;扩容时机。 3 hashmap的实现&#xff0c;以及hashmap扩容底层实现。 4 NIO了解么&#xff0c;讲一下和BIO的区别&#xff0c;AIO呢。阻塞&#xff0c;…

论文浅尝 | 常识用于回答生成式多跳问题

链接&#xff1a;https://arxiv.org/pdf/1809.06309.pdfAnsweringTasks多跳问题一般需要模型可以推理、聚合、同步上下文中不同的信息。就需要理解那些人类通过背景知识可以理解的限制关系。本文提出了一个很强的baseline模型&#xff08;multi-attention pointer-generator d…

中国智能投顾行业

原文地址&#xff1a; 中国智能投顾行业 一、概要 财富管理与新兴金融科技的结合&#xff0c;使得财富管理行业正在进入新的阶段——智能财富管理。近几年全球出现的智能投顾模式已然成为智能财富管理的一大热点。智能投顾&#xff0c;简而言之&#xff0c;就是基于投资者的投…

别让数据坑了你!用置信学习找出错误标注(附开源实现)

星标/置顶小屋&#xff0c;带你解锁最萌最前沿的NLP、搜索与推荐技术文 | JayLou娄杰&#xff08;NLP算法工程师&#xff0c;信息抽取方向&#xff09;编 | 北大小才女小轶美 | Sonata1 前言在实际工作中&#xff0c;你是否遇到过这样一个问题或痛点&#xff1a;无论是通过哪种…

助力句子变换:35W抽象、43W同义、13W简称三大知识库对外开源

句子变换&#xff0c;是指根据给定中文句子&#xff0c;借助某种语言处理手段&#xff0c;扩展出一定数据规模的中文句子集合&#xff0c;是一个从1到N的过程&#xff0c;目的在于解决搜索&#xff08;查询扩展&#xff09;、分类&#xff08;样本扩充&#xff09;、抽取&#…

数据结构--红黑树 Red Black Tree

文章目录1.概念2.操作2.1 左旋、右旋&#xff08;围绕某个节点的左/右旋&#xff09;2.2 插入2.3 删除3. 代码1.概念 二叉树在频繁动态增删后&#xff0c;可能退化成链表&#xff0c;时间复杂度由 O(lgn) 变成 O(n)。&#xff08;不平衡&#xff09;平衡二叉树&#xff0c;树中…

深度学习在用户画像标签模型中的应用

原文地址&#xff1a;https://blog.csdn.net/chaishen10000/article/details/79324016 最近一段时间都在学习深度学习&#xff0c;想着在用户画像标签模型中看能不能用上&#xff0c;终于&#xff0c;用了一个多月的时间&#xff0c;结合实际的场景和数据&#xff0c;搭建了一套…

最强京东Java面试题(共现场4面)

一面&#xff08;基础面&#xff1a;约1个小时&#xff09; 自我介绍&#xff0c;主要讲讲做了什么和擅长什么 springmvc和spring-boot区别 Autowired的实现原理 Bean的默认作用范围是什么&#xff1f;其他的作用范围&#xff1f; 索引是什么概念有什么作用&#xff1f;MyS…

工业界求解NER问题的12条黄金法则

星标/置顶小屋&#xff0c;带你解锁最萌最前沿的NLP、搜索与推荐技术文 | JayLou娄杰&#xff0c;夕小瑶编 | 可盐可甜兔子酱美 | Sonata众所周知&#xff0c;命名实体识别&#xff08;Named Entity Recognition&#xff0c;NER&#xff09;是一项基础而又重要的NLP词法分析任…

POJ 1577 Falling Leaves(二叉查找树)

题目链接&#xff1a;http://poj.org/problem?id1577 题目大意&#xff1a; 二叉查找树按照叶子节点&#xff0c;从下往上抹去该树&#xff0c;给出抹除字符序列&#xff0c;求该二叉树&#xff0c;并前序打印 解题思路&#xff1a; 最后抹除的是根节点&#xff0c;把抹除的…

最新阿里内推高级Java面试题

阿里Java一面题目 osi七层网络模型&#xff0c;五层网络模型&#xff0c;每次层分别有哪些协议 死锁产生的条件&#xff0c; 以及如何避免死锁&#xff0c;银行家算法&#xff0c;产生死锁后如何解决 如何判断链表有环 虚拟机类加载机制&#xff0c;双亲委派模型&…

智能投顾-用户画像、投资组合选择、推荐引擎、大数据挖掘

智能投顾面面观之AI慕课 原文地址&#xff1a;https://www.jianshu.com/p/437c895794e0?utm_campaignharuki&utm_contentnote&utm_mediumreader_share&utm_sourceweixin “最后编辑于 2017.11.14 21:49”>2017.11.13 11:47* 自我介绍 大家好&#xff0c;我是…

论文浅尝 | KG Embedding with Iterative Guidance from Soft Rules

论文链接&#xff1a;https://www.aaai.org/ocs/index.php/AAAI/AAAI18/paper/download/16369/16011发表会议&#xff1a;AAAI 2018摘要知识图谱表示学习旨在将实体和关系嵌入到向量空间&#xff0c;同时保留知识图谱的内在结构。传统方法主要基于关系三元组学习知识图谱的嵌入…

人工智能轨道交通行业周刊-第69期(2023.12.11-12.24)

本期关键词&#xff1a;集装箱智能管理、智慧工地、智能应急机器人、车辆构造、大模型推理 1 整理涉及公众号名单 1.1 行业类 RT轨道交通人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟VSTR铁路与城市轨道交通RailMetro轨…

可信知识实证在UGC时代情报应用中的思考与探索

可信知识实证在UGC时代情报应用中的思考与探索 在当前互联网高度发达、可发布信息源和信息渠道猛增且多元化的大背景下&#xff0c;信息形态变得广泛且多模。从传统的纸质文档&#xff0c;到中期的电子结构化文档、电子非结构化文本&#xff0c;再到如今的语音信息、图片信息、…