二叉树的操作(c++实现)

(1)采用二叉链表结构建立二叉树;
(2)编程实现二叉树的先序、中序、后序和层序遍历;
(3)编程实现:求二叉树的高度和叶的结点个数;
(4)应用实现:哈夫曼编码。

1.建立二叉树和遍历二叉树

#include <iostream>
#define m 100
typedef struct BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef struct{
    BiTree base;
    int front;
    int rear;
}SqQueue;
void CreatBiTree(BiTree &T);
void PreOrderTraverse(BiTree T);
void InOrderTraverse(BiTree T);
void PostOrderTraverse(BiTree T);
void Level(BiTree T);
void InitQueue(SqQueue &s);
void EnQueue(SqQueue &s,BiTree T);
BiTree DeQueue(SqQueue &s);
bool IsEmpty(SqQueue s);
using namespace std;
int main(){
    BiTree T;
    cout<<"先序遍历顺序建立二叉树为:"<<endl;
    CreatBiTree(T);
    cout<<"先序遍历输出为:"<<endl;
    PreOrderTraverse(T);
    cout<<endl;
    cout<<"中序遍历输出为:"<<endl;
    InOrderTraverse(T);
    cout<<endl;
    cout<<"后序遍历输出为:"<<endl;
    PostOrderTraverse(T);
    cout<<endl;
    cout<<"层序遍历输出为:"<<endl;
    Level(T);
    cout<<endl;
}
//先序建立二叉树
void CreatBiTree(BiTree &T){
    char ch;
    cin>>ch;
    if(ch=='#'){
        T=NULL;
    }else if(ch!='#' && ch!='!'){
        T=new BiTNode;
        T->data=ch;
        CreatBiTree(T->lchild);
        CreatBiTree(T->rchild);
    }
}
//先序遍历:若结点不为空输出根结点数据,再遍历左子树,遍历右子树;
//         若为空就不输出
void PreOrderTraverse(BiTree T){
    if(T){
        cout<<T->data<<" ";
        PreOrderTraverse(T->lchild);
        PreOrderTraverse(T->rchild);
    }
}
//中序遍历:若结点不为空就遍历左子树,输出根结点数据,再遍历右子树;
//         若为空就不输出
void InOrderTraverse(BiTree T){
    if(T){
        InOrderTraverse(T->lchild);
        cout<<T->data<<" ";
        InOrderTraverse(T->rchild);
    }
}
//后序遍历:若结点不为空就遍历左子树,然后遍历右子树,输出根结点数据;
//         若为空就不输出
void PostOrderTraverse(BiTree T){
    if(T){
        PostOrderTraverse(T->lchild);
        PostOrderTraverse(T->rchild);
        cout<<T->data<<" ";
    }
}
//层次顺序遍历:先进先出符合队列,先让第一层结点入队,然后依次入队;
//             依次出队就为层次顺序遍历
void Level(BiTree T){
    SqQueue s;
    if(T){
        InitQueue(s);
        EnQueue(s,T);
        while(!IsEmpty(s)){
            BiTree temp;
            temp=DeQueue(s);
            cout<<temp->data<<" ";
            if(temp->lchild){
                EnQueue(s,temp->lchild);
            }
            if(temp->rchild){
                EnQueue(s,temp->rchild);
            }
        }
    }
}
//进队列
void EnQueue(SqQueue &s,BiTree e){
    if(s.front==(s.rear+1)%m){
        cout<<"队列满了无法入队"<<endl;
    }else{
        s.base[s.rear]=*e;
        s.rear=(s.rear+1)%m;
    }
}
//出队列
BiTree DeQueue(SqQueue &s){
    BiTree e;
    if(s.front==s.rear){
        return NULL;
    }else{
        *e=s.base[s.front];
        s.front=(s.front+1)%m;
        return e;
    }
}
//初始化循环队列
void InitQueue(SqQueue &s){
    s.base=new BiTNode[m];
    s.front=s.rear=0;
}
bool IsEmpty(SqQueue s){
    if(s.front==s.rear){
        return true;
    }else{
        return false;
    }
}

2.二叉树高度和叶结点个数

#include <iostream>
typedef struct BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
void CreatBiTree(BiTree &T);
int Depth(BiTree T);
int LeafCount(BiTree T);
using namespace std;
int main(){
    BiTree T;
    cout<<"先序遍历顺序建立二叉树为:"<<endl;
    CreatBiTree(T);
    cout<<"该二叉树深度为:"<<Depth(T)<<endl;
    cout<<"该二叉树叶子结点个数为:"<<LeafCount(T)<<endl;
}
//先序建立二叉树
void CreatBiTree(BiTree &T){
    char ch;
    cin>>ch;
    if(ch=='#'){
        T=NULL;
    }else if(ch!='#' && ch!='!'){
        T=new BiTNode;
        T->data=ch;
        CreatBiTree(T->lchild);
        CreatBiTree(T->rchild);
    }
}
//深度
int Depth(BiTree T){
    if(T==NULL) return 0;
    else{
        int x=Depth(T->lchild);
        int y=Depth(T->rchild);
        if(x>y) return x+1;
        else return y+1;
    }
}
//叶子结点个数
int LeafCount(BiTree T){
    if(T==NULL){
        return 0;
    }else if(T->lchild==NULL && T->rchild==NULL){
        return 1;
    }else{
        return LeafCount(T->lchild)+LeafCount(T->rchild);
    }
}

3.哈夫曼编码

#include<iostream>
#define MAX 1000
using namespace std;
struct node {
	char val;
	int weight;
	int par, lSon, rSon;
}*Tree;
void BuildTree(node* &tree,int n);
void findMin(node*& tree,int maxn, int now);
void showTree(node* &tree, int n, int now,int cnt);
void Code(node* tree,int n);
int main(){
    cout<<" 10"<<endl;
    cout<<" /"<<" \\"<<endl;
    cout<<"d"<<"   6"<<endl;
    cout<<"   /"<<" \\"<<endl;
    cout<<"  c"<<"   3"<<endl;
    cout<<"     /"<<" \\"<<endl;
    cout<<"    a"<<"   b"<<endl;
    node* Tree;
	int n;
	cout<<"输入叶节点个数:"<<endl;
	cin >> n;
	BuildTree(Tree, n);
	cout<<"递归打印哈夫曼树的叶子结点:"<<endl;
	showTree(Tree,n,2*n-1,0);
	Code(Tree,n);
}
//构造哈夫曼树
void BuildTree(node* &tree,int n)
{
	int maxn=2*n;
	tree=new node[maxn];
	cout<<"请输入"<<n<<"个叶子结点的值和权值:"<<endl;
	for (int i=1;i<maxn;i++)
		tree[i].weight=tree[i].par=tree[i].lSon=tree[i].rSon=0;
	for (int i=1; i <=n; i++)
		cin>>tree[i].val>>tree[i].weight;
    cout<<"新建了"<<n-1<<"个结点,它们是:"<<endl;
	for (int i=n+1;i<maxn;i++)
		findMin(tree,maxn,i);
    cout<<"所有的结点为:"<<endl;
    for(int i=1;i<maxn;i++){
		cout <<"第"<<i<<"个结点的权值为"<<tree[i].weight<<
		",左孩子为"<<tree[i].lSon<<",右孩子为"<<tree[i].rSon<<endl;
	}
}
//找到两个最小的权值,已被选中过的结点的双亲下标改成新结点的下标
void findMin(node*& tree,int maxn, int now)
{
	int a;
	int val=9999999;
	//在不是双亲的结点中,找权值最小的作为新结点的左孩子
	for (int i=1;i<now;i++){
		if (!tree[i].par){
			if (tree[i].weight < val){
				a=i;
				val=tree[i].weight;
			}
		}
	}
	tree[now].lSon=a;
	tree[now].weight+=tree[a].weight;
	tree[a].par=now;
	val = 9999999;
	//在不是双亲的结点中,找权值最小的作为新结点的右孩子
	for (int i=1;i<now;i++){
		if (!tree[i].par)
			if (tree[i].weight < val)
			{
				a=i;
				val=tree[i].weight;
			}
	}
	tree[now].rSon=a;
	tree[a].par=now;
	tree[now].weight+=tree[a].weight;
	cout <<"第"<<now<<"个结点,其权值为"<<tree[now].weight<<",左孩子为"<<tree[now].lSon<<",右孩子为"<<tree[now].rSon<<endl;
}
//递归打印哈夫曼树的叶子结点
void showTree(node* &tree,int n,int now,int cnt)
{
	if (tree[now].lSon==0 && tree[now].rSon==0){
		cout<<"值为"<<tree[now].val<<"结点的权值为"<<tree[now].weight<<",路径长为"<<cnt<<endl;
	}
	else{
		if (tree[now].lSon != 0){
			showTree(tree,n,tree[now].lSon,cnt+1);
		}
		if (tree[now].rSon != 0){
			showTree(tree, n, tree[now].rSon,cnt+1);
		}
	}
}
//哈夫曼树编码
string HC[MAX];//哈夫曼编码数组
void Code(node* tree,int n)
{
    int start;
    char cd[n];
    string HC[n+1]="";
    cd[n-1]='\0';
    //给所有叶子结点编码
	for (int i=1;i<=n;i++){
        start=n-1;
        int c=i;
        int f=tree[i].par;
        while(f!=0){
            --start;
            if(tree[f].lSon==c) cd[start]='0';
            else cd[start]='1';
            c=f;
            f=tree[f].par;
        }
        for(int j=0;j<n-start-1;j++){
            HC[i]+=cd[start+j];
        }
        delete cd;
	}
	//打印编码
	cout<<"左孩子编码为0,右孩子编码为1"<<endl;
	for (int i=1;i<=n;i++){
		cout<<"第"<<i<<"个结点的编码为"<<HC[i]<<endl;
	}
}

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值