二叉树/前中后序遍历/二叉搜索树/哈夫曼树
作者:互联网
参考资料
目录中序遍历
左子树-->根节点-->右子树,在访问完成根节点后,接下来访问的下一个节点是右子树的最左边节点, 这个结论可用于中序线索二叉树的遍历
//非递归的中序遍历
#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef struct node
{
int data;
struct node* lchild; //左孩子
struct node* rchild; //右孩子
bool visite;
}BTNode;
void PreOrderWithoutRecursion(BTNode* root){
if (root == NULL)
return;
BTNode* p = root;
stack<BTNode*> s;
while (!s.empty() || p){
if(p!=NULL){
s.push(p);
p = p->lchild;
}else{
p = s.top();
cout<<p->data<<" ";
//根节点p以及它的左子树以及访问完成 p出栈 去往p的右子树
s.pop();
p = p->rchild;
}
}
}
int main(){
BTNode node[10];
for(int i=1;i<10;i++){
node[i].data = i;
node[i].lchild = NULL;//一开始结构体里面有其他数据,所以要初始化
node[i].rchild = NULL;
node[i].visite = false;
}
node[1].lchild = &node[2];
node[2].lchild = &node[4];
node[2].rchild = &node[5];
node[1].rchild = &node[3];
node[3].rchild = &node[6];
PreOrderWithoutRecursion(&node[1]);
return 0;
}
前序遍历
根节点-->左子树-->右子树,在访问完成一个节点后,接下来访问的下一个节点是
- 左节点存在就是左节点
- 左节点不存在,右节点存在就是右节点
- 如果是叶子节点,根据前序二叉线索树的线索找下一个节点
//非递归前序
#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef struct node
{
int data;
struct node* lchild; //左孩子
struct node* rchild; //右孩子
bool visite;
}BTNode;
void PreOrderWithoutRecursion(BTNode* root){
if (root == NULL)
return;
BTNode* p = root;
stack<BTNode*> s;
while (!s.empty() || p){
if(p!=NULL){
cout<<p->data<<" ";
s.push(p);
p = p->lchild;
}else{
p = s.top();
s.pop();
p = p->rchild;
}
}
}
int main(){
BTNode node[10];
for(int i=1;i<10;i++){
node[i].data = i;
node[i].lchild = NULL;//一开始结构体里面有其他数据,所以要初始化
node[i].rchild = NULL;
node[i].visite = false;
}
node[1].lchild = &node[2];
node[2].lchild = &node[4];
node[2].rchild = &node[5];
node[1].rchild = &node[3];
node[3].rchild = &node[6];
PreOrderWithoutRecursion(&node[1]);
return 0;
}
后序遍历
非递归后序遍历方式1
非递归的后序遍历需要用到标记位visite,只有左右2个子树都访问完成,才能访问根节点
//非递归的后序
#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef struct node
{
int data;
struct node* lchild; //左孩子
struct node* rchild; //右孩子
bool visite;
}BTNode;
//后序遍历
void AfterOrderWithoutRecursion(BTNode* root){
if (root == NULL)
return;
BTNode* p = root;
stack<BTNode*> s;
while (!s.empty() || p){
if(p->lchild!=NULL && !p->lchild->visite){
s.push(p);//回去的路
p = p->lchild;
} else if(p->rchild!=NULL && !p->rchild->visite){
s.push(p);
p = p->rchild;
} else {
cout<< p->data << " ";
p->visite = true;
p = s.top();
//mark: p==Null 说明栈已经空了,已经没有回去的路了
if(p==NULL)
break;
s.pop();
}
}
cout << endl;
}
int main(){
BTNode node[10];
for(int i=1;i<10;i++){
node[i].data = i;
node[i].lchild = NULL;//一开始结构体里面有其他数据,所以要初始化
node[i].rchild = NULL;
node[i].visite = false;
}
node[1].lchild = &node[2];
node[2].lchild = &node[4];
node[2].rchild = &node[5];
node[1].rchild = &node[3];
node[3].rchild = &node[6];
AfterOrderWithoutRecursion(&node[1]);
return 0;
}
非递归后序遍历方式2
#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef struct node
{
int data;
struct node* lchild; //左孩子
struct node* rchild; //右孩子
bool visite;
}BTNode;
//后续遍历
void AfterOrderWithoutRecursion(BTNode* root){
if (root == NULL)
return;
BTNode* p = root, *pre = NULL;//pre是上一次访问的节点
stack<BTNode*> s;
while (!s.empty() || p){
if(p!=NULL){
s.push(p);
p = p->lchild;
}else{
p = s.top();
//有有孩子且有孩子不是上一次访问的节点 说明右子树还没访问
if(p->rchild!=NULL && p->rchild!=pre){
p = p->rchild;
} else{
cout<<p->data<<" ";
pre = p ;
s.pop();
p = NULL;
}
}
}
}
int main(){
BTNode node[10];
for(int i=1;i<10;i++){
node[i].data = i;
node[i].lchild = NULL;//一开始结构体里面有其他数据,所以要初始化
node[i].rchild = NULL;
node[i].visite = false;
}
node[1].lchild = &node[2];
node[2].lchild = &node[4];
node[2].rchild = &node[5];
node[1].rchild = &node[3];
node[3].rchild = &node[6];
AfterOrderWithoutRecursion(&node[1]);
return 0;
}
二叉搜索树
插入节点
二叉搜索树的插入
#include<bits/stdc++.h>
using namespace std;
int ans = 0;
struct BSTNode{
BSTNode* lchild;
BSTNode* rchild;
int data;
};
int insert(int k,BSTNode* &T){ //注意这里是&
if(T==NULL){
T = (BSTNode*)malloc(sizeof (BSTNode));
T->rchild = T->lchild =NULL;
T->data = k;
return 1;
}
if(T->data==k) return 0;
if(k<T->data) return insert(k,T->lchild);
else return insert(k,T->rchild);
}
void inorder(BSTNode* T){
if(T==NULL) return;
inorder(T->lchild);
cout<<T->data<<" ";
inorder(T->rchild);
}
int main(){
BSTNode* root = NULL;//分配一块空间存指针类型
insert(5,root);
insert(3,root);
insert(1,root);
insert(6,root);
insert(7,root);
inorder(root);
return 0;
}
删除节点
1)没有左子树或者右子树 直接删除
2)有左子树和右子树,删除15节点,因为有先找到右子树最小的节点17
哈夫曼树
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x7fffffff;
string huffmanCode[20];//设立一个临时数组存哈弗曼编码
int sum;//节点个数
struct HuffNode
{
char data;//结点数据
int weight;//权值
int parent;
int lchild;
int rchild;
};
void Select(HuffNode* &T, int k, int& i1, int& i2) {
/*选择根结点权值最小的两个结点。*/
int min1 = inf , min2 = inf;
for(int i=0;i<k;i++){
if(T[i].parent==-1 && T[i].weight<min1){
min1 = T[i].weight;
i1 = i;
}
}
for(int i=0;i<k;i++){
if(T[i].parent==-1 && T[i].weight<min2 && i!=i1){
min2 = T[i].weight;
i2 = i;
}
}
}
void CreatHufftree(HuffNode* &T, int n){
int s1, s2;
int i;
if (n <= 1){
cout << "您输入的结点个数有误请输入的结点个数大于1" << endl;
return;
}
//首先!初始化!
for (i = 0; i <= 2 * n; i++){
T[i].parent = -1;
T[i].lchild = -1;
T[i].rchild = -1;
}
//进行归并 //进行n-1次的结合 //最后一个位置为2n-1 0~n-1是一开始存的初始节点
for (i = n ; i < 2 * n-1; i++){
//权值最小的两个结点归并成一个父结点 s1 s2作为返回值接收 s1,s2是T[]里面权重最小且没有合并的2个节点
Select(T, i , s1, s2);
T[i].weight = T[s1].weight + T[s2].weight;
T[s1].parent = i;
T[s2].parent = i;
T[i].lchild = s1;
T[i].rchild = s2;
}
}
void HuffmanCode(HuffNode* T, string huffmanCode[]) {
//设置一个临时存储空间
int cur;
int parent;
//遍历哈夫曼树,生成哈夫曼编码
for (int i = 0; i < sum; i++) {
cur = i;//记录当前处理位置
parent = T[i].parent;//找到当前结点的父节点
while (parent != -1) {//父节点不等于-1指的就是当前
if (T[parent].lchild == cur)
huffmanCode[i] = '0' + huffmanCode[i];//当前为左子树则编码0
else
huffmanCode[i] = '1' + huffmanCode[i];
//向上搜索
cur = parent;
parent = T[parent].parent;
}
}
}
int main(){
cin >> sum;//节点个数
//sum个初始节点合成哈夫曼树会再生成sum-1个新节点 一共2*sum-1个节点
HuffNode *T = new HuffNode[2 * sum];
//录入数据!
for (int i = 0; i < sum; i++){
cin >> T[i].data;
cin >> T[i].weight;
}
CreatHufftree(T, sum);
cout << "哈夫曼编码为:" << endl;
HuffmanCode(T, huffmanCode );
for (int i = 0; i < sum; i++){
cout << "结点" << T[i].data << ":" << huffmanCode[i] << endl;
}
return 0;
}
/*
6
a 45
b 13
c 12
d 16
e 9
f 5
*/
练习题
#include<bits/stdc++.h>
using namespace std;
int ans = 0;
struct node{long long l,r,val;}bt[1000002];
int book[1000002];//记忆化以该节点为根节点的树节点个数
int count(long long now){//递归的对左右子树计数
if(book[now]!=0) return book[now];
if(now==-1){
book[now] = 0;
} else{
book[now] = count(bt[now].l) + count(bt[now].r) + 1;
}
return book[now];
}
bool same(long long now1,long long now2){//判断是否对称 now是树的id
if(now1==-1&&now2==-1) return true;
if(now2==-1||now1==-1) return false;//小技巧
if(bt[now1].val!=bt[now2].val) return false;
//now1的左子树和now2的右子树一样 todo 可以将结果保存
return same(bt[now1].l,bt[now2].r)&&same(bt[now1].r,bt[now2].l);
}
int main(){
int n;cin>>n; //n个点
for(int i=1;i<=n;i++) cin>>bt[i].val; //每个点的值
for(int i=1;i<=n;i++) cin>>bt[i].l>>bt[i].r; //每个点的左孩子id和右孩子id
for(int i=1;i<=n;i++)/*枚举每棵子树*/
if(same(i,i))
ans=max(ans,count(i));
return 0&printf("%d",ans);
}
标签:return,struct,哈夫曼,前中,int,二叉树,NULL,root,节点 来源: https://www.cnblogs.com/cyfuture/p/16599155.html