树(Heap)
对于大量的输入数据,链表的线性访问时间太慢,不宜使用——《数据结构与算法分析——C 语言描述》 p 65
对于大量的输入数据,适合用树结构,大部分操作都是 O( log N )。
二叉树
1. 实现
节点定义
template<typename T>
struct Node
{
Node(T v) : val(v), left(nullptr), right(nullptr) {}; T val;
struct Node *left;
struct Node *right;
};
构建树并添加节点
按照如图的树构建

Node<int> *root = new Node<int>(); //根节点 root->left = new Node<int>(); //根节点的左子树
root->left->right = new Node<int>(); root->right = new Node<int>(); //根节点的又子树
root->right->left = new Node<int>();
root->right->left->left = new Node<int>();
root->right->right = new Node<int>();
遍历
递归方式
template<typename T>
void traversalRecursion(const struct Node<T>* const p)
{
if (p != nullptr)
{
cout << p->val; traversalRecursion(p->left);
traversalRecursion(p->right);
}
else
cout << "#";
}
非递归方式——用栈消除递归
template<typename T>
void traversalStack(struct Node<T> *const root)
{
stack<struct Node<T>*> s; s.push(root); while (s.size())
{
struct Node<T> *const p = s.top(); s.pop(); if (p == nullptr)
{
cout << "#";
continue;
} cout << p->val; s.push(p->right);
s.push(p->left);
}
}
表达式树
后缀表达式: a b + c d e + * *
从“后缀表达式”开始构造一颗表达式树,仅类定义
template<typename T>
class ExpressionTree
{
public:
struct Node<T>* initFormPostfix(const string &postfix)
{
istringstream iss(postfix);
T c; while (iss >> c)
{
struct Node<T> *const p = new struct Node<T>(c); switch (characterType(c))
{
case :
sk.push(p);
break; case :
p->right = sk.top(); sk.pop();
p->left = sk.top(); sk.pop(); sk.push(p);
break;
}
} return sk.top();
} private:
int characterType(const T &c) const
{
if (c == "+" || c == "-" || c == "*" || c == "/")
return ; return ;
} stack<struct Node<T>*> sk;
};
完整代码
#include <iostream>
#include <string>
#include <sstream>
#include <stack>
#include <memory> using namespace std; template<typename T>
struct Node
{
Node(T v) : val(v), left(nullptr), right(nullptr) {};
T val;
struct Node *left;
struct Node *right;
}; template<typename T>
class ExpressionTree
{
public:
struct Node<T>* initFormPostfix(const string &postfix)
{
istringstream iss(postfix);
T c; while (iss >> c)
{
struct Node<T> *const p = new struct Node<T>(c); switch (characterType(c))
{
case :
sk.push(p);
break; case :
p->right = sk.top(); sk.pop();
p->left = sk.top(); sk.pop(); sk.push(p);
break;
}
} return sk.top();
} private:
int characterType(const T &c) const
{
if (c == "+" || c == "-" || c == "*" || c == "/")
return ; return ;
} stack<struct Node<T>*> sk;
}; template<typename T>
void traversalRecursion(const struct Node<T>* const p)
{
if (p != nullptr)
{
cout << p->val; traversalRecursion(p->left);
traversalRecursion(p->right);
}
else
cout << "#";
} int main()
{
string postfix = "a b + c d e + * *"; ExpressionTree<string> et; const struct Node<string> *root = et.initFormPostfix(postfix); traversalRecursion(root); return ;
}
二叉查找树
构建
构建如图所示的二叉查找树

构建 + 遍历 代码如下
#include <iostream>
#include <initializer_list>
#include <stack> using namespace std; template<typename T>
struct Node
{
Node(T v) : val(v), left(nullptr), right(nullptr) {}
T val;
struct Node* left;
struct Node* right;
}; template<typename T>
class BinarySearchTree
{
public:
BinarySearchTree()
{
root = new struct Node<T>();
} BinarySearchTree(const initializer_list<T> il) : BinarySearchTree()
{
initializer_list<T>::iterator it = il.begin(); root->val = *it++; while (it != il.end())
insert(*it++);
} void insert(const T &val)
{
struct Node<T> **p = &root; while (*p != nullptr)
{
if (val == (*p)->val)
return; if (val < (*p)->val)
{
p = &((*p)->left);
continue;
} if (val > (*p)->val)
{
p = &((*p)->right);
continue;
}
} *p = new struct Node<T>(val);
} void traversalStack()
{
stack<struct Node<T>*> s; s.push(root); while (s.size())
{
struct Node<T> *const p = s.top(); s.pop(); if (p == nullptr)
{
cout << "#";
continue;
} cout << p->val; s.push(p->right);
s.push(p->left);
}
} private:
struct Node<T> *root;
}; int main(void)
{
BinarySearchTree<int> bst({ , , , , , , , , }); bst.traversalStack(); return ;
}
查找 代码如下
struct Node<T>* find(const T &val) const
{
struct Node<T> *p = root; while (p != nullptr)
{
if (p->val == val)
return p; if (val < p->val)
p = p->left; if (val > p->val)
p = p->right;
} return nullptr;
}
树的遍历
后序遍历
利用后序遍历求树的深度
unsigned getBinaryTreeHeigt(const struct Node *const p)
{
if (p == nullptr)
return -;
else
return + max(getBinaryTreeHeigt(p->left), getBinaryTreeHeigt(p->right));
}
层序遍历
代码一,非递归实现
void levelOrderTraversal(struct Node *root)
{
queue<struct Node*> q; q.push(root); while (q.size())
{
struct Node *p = q.front(); q.pop(); if (p == nullptr)
continue; q.push(p->left);
q.push(p->right); cout << p->val << " ";
}
}
代码二,递归实现
void levelVisit(queue<struct Node*> &que) {
if (que.empty()) return;
struct Node *p = que.front(); que.pop();
if (p == nullptr) return;
cout << p->val << " ";
que.push(p->left);
que.push(p->right);
levelVisit(que);
}
利用队列可以完成二叉树的层序遍历(广度优先遍历);利用栈可以完成二叉树的深度优先遍历。
树(Heap)的更多相关文章
- BZOJ.3489.A simple rmq problem(主席树 Heap)
题目链接 当时没用markdown写,可能看起来比较难受...可以复制到别的地方看比如DevC++. \(Description\) 给定一个长为n的序列,多次询问[l,r]中最大的只出现一次的数.强 ...
- 清北学堂 2020 国庆J2考前综合强化 Day2
目录 1. 题目 T1 一 题目描述 Sol T2 二 题目描述 Sol T3 三 题目描述 Sol T4 四 题目描述 Sol 2. 算法 -- 数据结构 1. 题目 T1 一 题目描述 问题描述 ...
- 左偏树(Leftist Heap/Tree)简介及代码
左偏树是一种常用的优先队列(堆)结构.与二叉堆相比,左偏树可以高效的实现两个堆的合并操作. 左偏树实现方便,编程复杂度低,而且有着不俗的效率表现. 它的一个常见应用就是与并查集结合使用.利用并查集确定 ...
- Codeforces Round #300 F - A Heap of Heaps (树状数组 OR 差分)
F. A Heap of Heaps time limit per test 3 seconds memory limit per test 512 megabytes input standard ...
- zoj-3963 Heap Partition(贪心+二分+树状数组)
题目链接: Heap Partition Time Limit: 2 Seconds Memory Limit: 65536 KB Special Judge A sequence ...
- 笛卡尔树 POJ ——1785 Binary Search Heap Construction
相应POJ 题目:点击打开链接 Binary Search Heap Construction Time Limit: 2000MS Memory Limit: 30000K Total Subm ...
- POJ-1785-Binary Search Heap Construction(笛卡尔树)
Description Read the statement of problem G for the definitions concerning trees. In the following w ...
- L - A Heap of Heaps CodeForces - 538F 主席树
L - A Heap of Heaps CodeForces - 538F 这个是一个还比较裸的静态主席树. 这个题目的意思是把这个数组变成k叉树,然后问构成的树的子树小于等于它的父节点的对数有多少. ...
- POJ 1785 Binary Search Heap Construction(裸笛卡尔树的构造)
笛卡尔树: 每个节点有2个关键字key.value.从key的角度看,这是一颗二叉搜索树,每个节点的左子树的key都比它小,右子树都比它大:从value的角度看,这是一个堆. 题意:以字符串为关键字k ...
随机推荐
- HDU-1166敌兵布阵(线段树)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submissi ...
- 44(function pointer 2)
#include<iostream> using namespace std; class A { public: int x; int sayhello() { cout<< ...
- netcat/curl/wget/smb/icmp ping -p/dns/telnet
通过SMB协议,在目标服务器和主机之间建立网络共享连接,然后将目标服务器上的文件做分享,接着就可以在主机端将分享的文件copy下来啦.操作的命令如下, net use h: \\xxx.xxx.xxx ...
- kubernetes实战(十一):k8s使用openLDAP统一认证
1.基本概念 为了方便管理和集成jenkins,k8s.harbor.jenkins均使用openLDAP统一认证. 2.部署openLDAP 此处将openLDAP部署在k8s上,openLDAP可 ...
- mysql 数据操作 多表查询 子查询 虚拟表介绍
子查询 把一个sql语句放在括号里 ,这个括号里sql语句查询结果其实就是一张表,并且是一个临时在内存里存在的虚拟表 可以用括号把一个查询sql语句括起来 得到查询的结果并且用as 为这张虚拟表起个别 ...
- 群用户通过微信小程序可以更好地协作了
今天,小程序向开发者开放了群ID的接口能力.简单地说,就是当你把小程序分享在群聊中,被点击后开发者可获取群ID和群名称,也方便更好地针对群场景提供个性化服务.不同的群有各自的群ID,那么这个新能力开发 ...
- google浏览器mac上跨域问题解决
open -n /Applications/Google\ Chrome.app/ --args --disable-web-security --user-data-dir=/Users/ /Use ...
- SQLSERVER数据导入到MYSQL
SQLSERVER数据导入到MYSQL http://hi.baidu.com/luck001221/item/cb4462299f9ea79ab73263d2?qq-pf-to=pcqq.group ...
- MutationObserver 监听DOM树变化
1 概述 Mutation observer 是用于代替 Mutation events 作为观察DOM树结构发生变化时,做出相应处理的API.为什么要使用mutation observer 去代替 ...
- mui笔记
1.关闭当前页面执行上一个页面的方法 var preview = plus.webview.currentWebview().opener() //获取当前窗口的创建者,即A preview.eval ...