9.1 树与二叉树

二叉树的存储

struct node {typename data;node* lchild;node* rchild;
};

新建节点

node* newNode(int v) {node* Node = new node;Node->data = v;Node->lchild = Node->rchild = NULL;return Node;
}

二叉树的查找

void search(node* root, int x, int newdata) {if (root == NULL) return ;if (root->data == x) {root->data = newdata;}search(root->lchild, x, newdata);search(root->rchild, x, newdata);
};

9.2 二叉树的遍历

9.2.1 先序遍历

递归

void PreOrder(node T){   //先序递归遍历二叉树 if(T == NULL){return ;}cout<<T->data<<" ";PreOrder(T->lchild );PreOrder(T->rchild );
}

非递归

void fPreOrder(node root){  //非递归先序遍历二叉树 if (root == NULL) {return;}Tnode p = root;stack<node> s;while (!s.empty() || p) {while(p){ //一直往左走 , 先序遍历cout<<p->data<<' ' ;s.push(p);p=p->lchild ; }//已经走到最左儿子if(!s.empty() ){p = s.top() ;//弹出父节点s.pop() ;p = p->rchild ;  //然后去父节点的右儿子先序遍历}}
}

9.2.2 中序遍历

递归

void InOrder(node T) {if(T == NULL){return ;}InOrder(T->lchild);cout<<T->data<<" ";  InOrder(T->rchild);
}

非递归

void fInOrder(node root) {  //非递归中序遍历二叉树 if(root == NULL)return ;Tnode p = root;stack<node> s;while (!s.empty() || p) {while(p) {s.push(p);p=p->lchild ;}if(!s.empty()) {p=s.top();s.pop();cout<<p->data<<' ' ;p=p->rchild ;}}
}

9.2.3 后序遍历

递归

void InOrder(node T) {if(T == NULL){return ;}InOrder(T->lchild); InOrder(T->rchild);cout<<T->data<<" ";
}

非递归

9.2.4 层序遍历

struct node {int data;int layer;node* lchild;node* rchild;
};
void LayerOrder(node* root) {queue<node*> q;root->layer = 1;//根节点层号为1q.push(root);while(!q.empty()) {node* now = q.front();q.pop();cout<<now->data<<" ";if (now->lchild != NULL) {now->lchild-layer = now_layer + 1;q.push(now->lchild);}if (now->rchild != NULL) {now->rchild->layer = now_layer + 1;q.push(now->rchild);}}
}

9.2.5 给定先序遍历和中序遍历求重建二叉树

//当前先序序列区间为[preL,preR], 中序序列区间为[inL, inR],返回根节点的地址
node* create(int preL, int preR, int inL, int inR) {if(preL > preR) return NULL;node* root = new node;//存放二叉树的根节点root->data = pre[preL];int k;for(k = inL; k <= inR; k++) {if (in[k] == pre[preL]) {break;}}int numLeft = k - inL;//左子树节点的个数root->lchild = create(preL + 1, preL + numLeft, inL, k - 1);root->rchild = creat(preL + numLeft + 1, preR, k + 1, inR);return root;
}

【PAT A1020】 Tree Traversals

Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder and inorder traversal sequences, you are supposed to output the level order traversal sequence of the corresponding binary tree.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (≤30), the total number of nodes in the binary tree. The second line gives the postorder sequence and the third line gives the inorder sequence. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in one line the level order traversal sequence of the corresponding binary tree. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the end of the line.

Sample Input:

7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
结尾无空行

Sample Output:

4 1 6 3 5 7 2
结尾无空行

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 50;
struct node {int data;node* lchild;node* rchild;
};
int pre[maxn], in[maxn], post[maxn];
int n;//节点数
//当前后序序列区间为[postL,postR], 中序序列区间为[inL, inR],返回根节点的地址
node* create(int postL, int postR, int inL, int inR) {if(postL > postR) return NULL;node* root = new node;//存放二叉树的根节点root->data = post[postR];int k;for(k = inL; k <= inR; k++) {if (in[k] == post[postR]) {break;}}int numLeft = k - inL;//左子树节点的个数root->lchild = create(postL + 1, postL + numLeft - 1, inL, k - 1);root->rchild = creat(postL + numLeft, postR - 1, k + 1, inR);return root;
}void LayerOrder(node* root) {queue<node*> q;root->layer = 1;//根节点层号为1q.push(root);while(!q.empty()) {node* now = q.front();q.pop();cout<<now->data<<" ";if (now->lchild != NULL) {q.push(now->lchild);}if (now->rchild != NULL) {q.push(now->rchild);}}
}
int main() {scanf("%d",&n);for (int i = 0; i < n; i++) {scanf("%d", &post[i]);}for (int i = 0; i < n ; i++) {scanf("%d", &in[i]);}node* root = create(0,n-1,0,n-1);LayerOrder(root);return 0;
}

9.2.5 二叉树的静态实现

struct node{typename data;int lchild;int rchild;
} Node[maxn];

9.3 树的遍历

9.3.1 树的静态写法

struct node {typename data;//数据域int child[maxn];//指针域,存放所有子节点的下标
} Node[maxn]; //节点数组由于无法预知子节点的个数,所以child数组的长度只能开到最大。因此可以使用变长数组vector表示
struct node {typename data;//数据域vector<node> child;//指针域
} Node[maxn];

9.3.2 树的先根遍历

void PreOrder(int root) {printf("%d ", Node[root].data);for (int i = 0; i < Node[root].child.size(); i ++) {PreOrder(Node[root].child[i]);}
}

9.3.3 树的层序遍历

void LayerOrder(int root) {queue<int> Q;Q.push(root);while(!Q.empty()) {int front = Q.front();printf("%d ",Node[front].data);Q.pop();for (int i = 0; i < Node[front].child.size(); i++) {Q.push(Node[front].child[i]);}}
}

【PAT A1053】Path of Equal Weight

Given a non-empty tree with root R, and with weight Wi​ assigned to each tree node Ti​. The weight of a path from R to L is defined to be the sum of the weights of all the nodes along the path from R to any leaf node L.

Now given any weighted tree, you are supposed to find all the paths with their weights equal to a given number. For example, let's consider the tree showed in the following figure: for each node, the upper number is the node ID which is a two-digit number, and the lower number is the weight of that node. Suppose that the given number is 24, then there exists 4 different paths which have the same given weight: {10 5 2 7}, {10 4 10}, {10 3 3 6 2} and {10 3 3 6 2}, which correspond to the red edges in the figure.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 0<N≤100, the number of nodes in a tree, M (<N), the number of non-leaf nodes, and 0<S<230, the given weight number. The next line contains N positive numbers where Wi​ (<1000) corresponds to the tree node Ti​. Then M lines follow, each in the format:

ID K ID[1] ID[2] ... ID[K]

where ID is a two-digit number representing a given non-leaf node, K is the number of its children, followed by a sequence of two-digit ID's of its children. For the sake of simplicity, let us fix the root ID to be 00.

Output Specification:

For each test case, print all the paths with weight S in non-increasing order. Each path occupies a line with printed weights from the root to the leaf in order. All the numbers must be separated by a space with no extra space at the end of the line.

Note: sequence {A1​,A2​,⋯,An​} is said to be greater than sequence {B1​,B2​,⋯,Bm​} if there exists 1≤k<min{n,m} such that Ai​=Bi​ for i=1,⋯,k, and Ak+1​>Bk+1​.

Sample Input:

20 9 24
10 2 4 3 5 10 2 18 9 7 2 2 1 3 12 1 8 6 2 2
00 4 01 02 03 04
02 1 05
04 2 06 07
03 3 11 12 13
06 1 09
07 2 08 10
16 1 15
13 3 14 16 17
17 2 18 19
结尾无空行

Sample Output:

10 5 2 7
10 4 10
10 3 3 6 2
10 3 3 6 2
结尾无空行

题意:就是给定一个target,求从根节点到叶节点的路径,路径上所有节点的权重和等于target。有的话输出多条,按照权重从大到小输出。

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN = 100;struct node {int weight;vector<int> child;
} Node[MAXN];bool cmp(int a, int b) {return Node[a].weight > Node[b].weight;
}
int n, m, S;
int path[MAXN];//路径//当前访问节点为index,numNode为当前路径path上的节点的个数(层数)
void DFS(int index, int numNode, int sum) {if(sum > S) return;if(sum == S) {if(Node[index].child.size() != 0) return;for(int i = 0; i < numNode; i ++) {printf("%d", Node[path[i]].weigth);if(i < numNode - 1) printf(" ");else printf("\n");}return;}for (int i = 0; i < Node[index].child.size(); i++) {int child = Node[index].child[i];path[numNode] = child;DFS(child, numNode + 1, sum + Node[child].weight);//递归进入下一层}
}
int main() {scanf("%d%d%d", &n, &m, &S);for (int i = 0; i <n; i ++) {scanf("%d", &Node[i].weight);}int id, k, child;for(int i = 0; i < m; i++) {   scanf("%d%d", &id, &k);Node[id].child.push_back(child);}sort(Node[i].child.begin(), Node[id].child.end(),cmp);
}path[0] = 0;DFS(0,1,Node[0].weight);return 0;
}

9.4 二叉查找树

9.4.2 二叉查找树的基本操作

1.查找操作

void search(node* root, int x) {if (root == NULL) return;if (x == root->data){printf("查找成功");} else if (x < root->data) {search(root->lchild, x);} else {search(root->rchild, x);}
}

2.插入操作

void insert(node* &root, int x) {if (root == NULL) {root = newNode(x);return;}if (x == root->data) {return;} else if (x < root->data) {insert(root->lchild, x);} else {insert(root->rchild, x);}
}

3.二叉树的建立

node* Create(int data[], int n) {node* root = NULL;for (int i = 0; i < n; i++) {insert(root, data[i]);}return root;
}

4. 二叉树的删除

把以二叉查找树中比节点权重小的最大节点称为该节点的前驱,而把比权重大的最小节点称为该节点的后继。

//寻找以root为根节点的树中的最大权值节点
node* findMax(node* root) {while (root->rchild != NULL) {root = root->rchild;}return root;
}//寻找以root为根节点的树中的最小权值节点
node* findMax(node* root) {while (root->lchild != NULL) {root = root->lchild;}return root;
}

void deleteNode(node* &root, int x) {if (root == NULL) return;if (root->data == x) {if(root->lchild == NULL  && root->rchild == NULL) {root = NULL;} else if(root->lchild != NULL){node* pre = findMax(root->lchild);    root->data = pre->data;       deleteNode(root->lchild,pre->data);} else {node* next = findMin(root->rchild);root->data = next->data;deleteNode(root->rchild, next->data);}} else if(root->data > x) PdeleteNode(root->lchild, x);} else {deleteNode(root->rchild, x);}
}

【PAT A1043】Is it a Binary Search Tree

9.5 平衡二叉树

9.5.1.平衡二叉树的定义

struct node {int v, height;//v为节点权重,height为当前子树高度node* lchild, *rchild;
};
node* newNode(int v) {node* Node = new node;Node->height = 1;Node->v = v;Node->lchild = Node->rchild = NULL;return Node;
}
int getHeight(node* root) {if(root == NULL) return 0;return root->height;
}int getBalanceFactor(node* root) {return getHeight(root->lchild) - getHeight(root->rchild);
}void updateHeight(node* root) {root->height = max(getHeight(root->lchild),getHeight(root->rchild)) + 1;
}

9.5.2 平衡二叉树的基本操作

1.查找操作

同二叉查找树

2.插入操作

左旋

void L(node* &root) {node* temp = root->rchild;root->rchild = temp.lchild;temp->lchild = root;updateHeight(root);updataHeight(temp);root = temp;
}

右旋

void R(node* &root) {node* temp = root->lchild;root->lchild = temp->rchild;temp->rchild = root;updateHeight(root);updateHeight(temp);root = temp;
}

void insert(node* &root, int v) {if(root == NULL) {root = newNode(v);return;}if(v < root->v) {insert(root->lchild);updateHeight(root);    if(getBalanceFactor(root) == 2) {if(getBalanceFactor(root->lchild == 1) {    //LL型R(root);} else if(getBalanceFactor(root->lchild) == -1) {//LR型L(root->lchild);R(root);}}} else {insert(root->rchild, v);    updateHeight(root);if(getBalanceFactor(root) == -2) {if(getBalanceFactor(root->lchild == -1) {    //RR型L(root);} else if(getBalanceFactor(root->lchild) == 1) {//LR型R(root->Rchild);L(root);}}}
}

9.6 并查集

9.6.1 并查集的定义

并查集的实现:其实就是一个数组:int father[N]

father[i]表示元素i的父节点,父节点本身也是这个集合内的元素。如果father[i] = i表示元素i是集合的根节点。对同一个集合来说,只存在一个根节点,且将其作为所属集合的标识。

9.6.2 并查集的基本操作

//1.初始化
for (int i = 1; i <= N; i++) {father[i] = i;
}//2.查找
int findFather(int x) {while(x != father[x]) {x = father[x];}return x;
}//3.合并
void Union(int a, int b) {int faA = findFather(a);int faB = findFather(b);if (faA != faB) {father[faA] = faB;}
}

9.6.3 路径压缩

路径压缩相当于把当前查询路径上所有节点的父亲都直接指向根节点。

int findFather(int x) {int a = x;while (x != father[x]) {x = father[x];}while(a != father[a]) {int z = a;a = father[a];    father[z] = x;}return x;
}//递归xief
int findFather(int v) {if(v == father[v]) {return v;} else {int F = findFather[father[v]);father[v] = F;return F;}
}

9.7 堆

9.7.1 堆的定义与基本操作

使用数组来表示堆,并且数组第i号位的节点的左孩子就是2i号位,而右孩子则是(2i+1)号位。

const int maxn = 100;
int heap[maxn],n=10;
//对heap数组在[low, high]范围内进行向下调整
void downAdjust(int low, int high) {int i = low, j = 2 * i;//i为欲调整节点,j为其左孩子while (j <= high) {if(j + 1 <= high && heap[j + 1] > heap[j]) {j = j + 1;}if(heap[j] > heap[i]) {//以最大堆为例swap(heap[i], heap[j]);i = j;j = i * 2;} else {break;}}
}//建堆
void createHeap() {for (int i = n / 2; i >= 1; i--) {downAdjust(i,n);}
}//删除堆顶元素
void deleteTop() {heap[1] = heap[n--];downAdjust(1, n);
}//对heap数组在[low, high]范围内进行向上调整
void upAdjust(int low, int high) {int i = high, j = i / 2;while (j >= low) {if(heap[j] < heap[i]) {swap(heap[i], heap[j]);i = j;j = i / 2;} else {break;}}
}//添加元素
void insert(int x) {heap[++n] = x;upAdjust(1,n);
}

9.7.2 堆排序

void heapSort() {createHeap();for (int i = n; i > 1; i--) {swap(heap[i], heap[1]);downAdjust(1, i-1);}
}

9.8 哈夫曼树

9.8.1 哈夫曼树

#include<cstdio>
#include<queue>
using namespace std;priority_queue<long long, vector<long long>, greater<long long>> q;int main() {int n;long long temp, x, y, ans = 0;scanf("%d",&n);for (int i = 0; i < n; i ++) {scanf("%lld",&temp);q.push(temp);}while(q.size() > 1) {x = q.top();    q.pop();    y = q.top();q.pop();q.push(x + y);ans += x + y;}printf("%lld\n",ans);return 0;
}

9.8.2 哈夫曼编码

此部分留给有兴趣的读者自行实现。

算法笔记.胡凡 第九章 二叉树相关推荐

  1. 算法笔记.胡凡 第四章 算法初步

    4.1 排序 4.1.1 选择排序 void selectSort(int A[], int n) {for (int i = 0; i < n; i++) {int k = i;for (in ...

  2. 算法笔记.胡凡 第五章 数学问题

    5.1 简单数学 [PAT A1069] For any 4-digit integer except the ones with all the digits being the same, if ...

  3. 算法笔记胡凡 第3章 入门篇

    3.5进制转换 P进制的数转换为Q进制的数,分为两步: ①将P进制的数x转换为十进制数y ②将十进制数y转换为Q进制数z 除基取余法 [PAT B1022] D进制的A+B 输入两个非负 10 进制整 ...

  4. 算法笔记.胡凡 第11章 动态规划专题

    11.1 动态规划的递归写法和递推写法 11.1.1 动态规划的递归写法 以斐波那契数列为例,递归代码为 int F(int n) {if (n == 0 || n == 1) return 1;el ...

  5. 算法笔记.胡凡 第6章 C++标准模板库(STL)介绍

    6.1 vector常见用法详解 6.1.1.vector定义 vector<int> name; 6.1.2.vector容器元素访问 (1) 下标:v[0] (2)迭代器 vector ...

  6. 算法笔记 胡凡 codeup 数列

    数列 题目链接:http://codeup.cn/problem.php?cid=100000583&pid=1 思路 由于该章节用的是递归,所以就采用递归方式来写而不是动态规划 这样的重复度 ...

  7. 算法笔记 胡凡 codeup 吃糖果

    吃糖果 题目链接:http://codeup.cn/problem.php?cid=100000583&pid=0 思路 就是简单的递归 两种方法:当n只糖果时,可以分为 吃一只糖果,剩下n- ...

  8. 算法笔记胡凡 7.3.4 连接各点时代码有误

    在此书7.3.4中, 静态链表结点定义如下: struct Node{typename data;int next; }node[size]; 书中要将11111,22222,33333三个地方的节点 ...

  9. 《算法笔记--胡凡,曾磊主编》set的用法

    set的用法 set 翻译为集合,是一个内部有序且不重复的容器 #include<set> using namespace std;set的定义 定义一个set : set<type ...

最新文章

  1. oc 调用c语言方法和oc的方法调用
  2. php webserver documentroot,php – 在包含中使用$_SERVER [‘DOCUMENT_ROOT’]是个好主意?...
  3. 关于 .Net Core runtimeconfig 文件说明
  4. 云原生领域首本架构白皮书,你Get到了吗?
  5. maven私有库配置
  6. centos php 默认安装目录,centos系统中的软件安装目录在哪
  7. sql server 查询本周、本月所有天数的数据
  8. snmp基本介绍--理解OID/MIB/snmp报文类型/snmp版本
  9. 获取客户端的IP地址
  10. MyEclipse中解决“Save could not be completed”问题!
  11. php怎么产生随机数,php怎么生成随机数
  12. 底层驱动 【One Day】gec6818开发板刷屏+secureCRT+tftpd32.334安装教程+SD启动卡教程
  13. 基于Linux的录像机:Neuros OSD
  14. cityengine常用规则函数
  15. router禁用443端口
  16. OCR识别缺点_常用的OCR文字识别软件有哪些_软件动态论坛
  17. Zigbee基础理论知识总结
  18. 计算机台式机快捷键开机,电脑快捷键如何快速开关机
  19. 线上打印马上送,支持线上打印文档的软件
  20. ban aviator wholesale new era|Be Happy! One of the Greatest Sources of Happiness—Nature_4899

热门文章

  1. fileupload.class.php,PHP 文件上传类 FileUpload 高洛峰老师 细说PHP
  2. x50pro怎么升级鸿蒙系统,被央视点赞的vivo X50 Pro拍照如何?实测告诉你
  3. 农民工如何拥有500多家加盟连锁店,看他是怎样做到的?
  4. java 设置pdf 编码格式_Java 在PDF中添加条形码
  5. 如何注册和设置 zoom Background
  6. HDU 2826 || The troubles of lmy(判断两个N边形是否相似
  7. OpenCV之彩色视频转黑白视频
  8. VIM7.3中文手册
  9. 仿微信个人二维码切换样式
  10. 编写python代码实现打开并登录网页、对网页进行点击、输入信息等操作