二叉树

二叉树

二叉树的相关概念

1.子节点,根节点,兄弟节点,双亲节点
2.度:拥有多少个子节点,0,1,2
3.深度:二叉树的行数
4.满二叉树:节点个数为2^k-1 完全二叉树:最下面那层的右边可以少些节点

二叉树的性质

1.二叉树的第i层最多的节点数为2^(i-1)
2.深度为k的二叉树节点数最多有2^k-1
3.设度为0的节点数个数为n0,度为1的节点数个数为n1,度为2的节点数个数为n2,则节点总数n=n1+n2+n0
又因为节点总数n=孩子节点+根节点=n1+n2*2+1,所以n0=n2+1

树的建立
#include<iostream>
using namespace std;
#define maxsize 100
typedef char datatype;

typedef struct
{
    datatype data;
    int parent;
}ptree;
ptree *T[maxsize];
ptree *create()
{
    datatype data;
    int num;
    int rear;
    ptree *root, *s;
    rear = 0;
    root = NULL;
    cin >> data >> num;
    while (data != '#')
    {
        s = NULL;

        if (data != '0')
        {
            s = (ptree*)malloc(sizeof(ptree));
            s->data = data;
            s->parent = num;
        }
        T[rear] = s;
        if (T[rear]->parent == 0)root = T[rear];
        rear++;
        cin >> data >> num;
    }
    return root;
}

int main()
{
    ptree p;
    p = *create();
    return 0;
}

二叉树的存储
bitree* createbitree()
{
    char ch;
    int fornt, rear;//队头和队尾指针
    bitree *root, *s;
    fornt = 1;rear = 0;
    root = NULL;//置空二叉树
    ch = getchar();//输入第一个字符
    while (ch != '\n')
    {
        s = NULL;
        if (ch != '@')
        {
            s = (bitree*)malloc(sizeof(bitree));
            s->data = ch;
            s->lchild = NULL;
            s->rchild = NULL;
        }
        rear++;
        Q[rear] = s;//入队
        if (rear == 1) root = s;
        else
        {
            if (s && Q[fornt])//孩子节点和双亲节点都存在
                if (rear % 2 == 0)Q[fornt]->lchild = s;//rear为偶数,新节点是左孩子
                else Q[fornt]->rchild = s;//新节点是右孩子
            if (rear % 2 == 1)fornt++;//两个孩子处理完毕出队列
        }
        ch=getchar();
    }
    return root;
}

bitree *creat()   /*建立二叉树的递归算法*/
{
	bitree *t;
	int x;
	scanf("%d", &x);
	if (x == 0) t = NULL; /*以x=0表示输入结束*/
	else {
		t = (bitree*)malloc(sizeof(bitree));/*动态生成结点t,分别给结点t的数据域、左右孩子域                   赋值,给左右孩子域赋值时用到了递归的思想。*/
		t->data = x;
		t->lchild = creat();
		t->rchild = creat();
	}
	return t;
}
二叉树的遍历

1.前序遍历
(1)访问根节点
(2)遍历左子树
(3)遍历右子树
2.中序遍历
(1)遍历左子树
(2)访问根节点
(3)遍历右子树
3.后序遍历
(1)遍历左子树
(2)遍历右子树
(3)访问根节点

void inorder(bitree *t)  /*中序遍历二叉树的递归算法*/
{
	if (t != NULL)
	{
		inorder(t->lchild);
		printf("%4d", t->data);
		inorder(t->rchild);
	}
}
void inorderf(bitree *t)  /*前序遍历二叉树的递归算法*/
{
	if (t != NULL)
	{
		printf("%4d", t->data);
		inorder(t->lchild);
		inorder(t->rchild);
	}
}
void inorderb(bitree *t)  /*后序遍历二叉树的递归算法*/
{
	if (t != NULL)
	{
		inorder(t->lchild);
		inorder(t->rchild);
		printf("%4d", t->data);
	}
}
小例子
#include<stdio.h>
#include<stdlib.h>
#define M 100
typedef struct node /*二叉链表结点结构*/
{
    int data;  /*数据域*/
    int rtag, ltag;//用来判断孩子节点是否存在,0是存在,1是不存在
    struct node *lchild, *rchild;/*左、右孩子域*/
} bitree;
bitree *pre = NULL;
bitree *que[M]; /*定义一个指针数组,说明队列中的元素类型为bitree指针类型*/
int front = 0, rear = 0; /*初始化循环队列*/

bitree *creat()   /*建立二叉树的递归算法*/
{
    bitree *t;
    int x;
    scanf("%d", &x);
    if (x == 0) t = NULL; /*以x=0表示输入结束*/
    else {
        t = (bitree*)malloc(sizeof(bitree));/*动态生成结点t,分别给结点t的数据域、左右孩子域                   赋值,给左右孩子域赋值时用到了递归的思想。*/
        t->data = x;
        t->lchild = creat();
        t->rchild = creat();
    }
    return t;
}
void inorder(bitree *t)  /*中序遍历二叉树的递归算法*/
{
    if (t != NULL)
    {
        inorder(t->lchild);
        printf("%4d", t->data);
        inorder(t->rchild);
    }
}
void inorderf(bitree *t)  /*前序遍历二叉树的递归算法*/
{
    if (t != NULL)
    {
        printf("%4d", t->data);
        inorder(t->lchild);
        inorder(t->rchild);
    }
}
void inorderb(bitree *t)  /*后序遍历二叉树的递归算法*/
{
    if (t != NULL)
    {
        inorder(t->lchild);
        inorder(t->rchild);
        printf("%4d", t->data);
    }
}
void enqueue(bitree *t)  /*把bitree类型的结点*t入队列*/
{if (front != (rear + 1) % M) /*判断队列是否已满*/
{
    rear = (rear + 1) % M;
    que[rear] = t;
}
}

bitree *delqueue()
{
    if (front == rear) /*判断队列不为空*/
        return NULL;
    front = (front + 1) % M;
    return (que[front]);

}

void levorder(bitree *t) /*层次遍历二叉树的算法,说实话,思想不错*/
{
    bitree *p;
    if (t != NULL)
    {
        enqueue(t); /*根结点入队*/
        while (front != rear) /*当当前队列不为空时*/
        {
            p = delqueue();
            printf("%4d", p->data);
            if (p->lchild != NULL)
                enqueue(p->lchild);
            if (p->rchild != NULL)
                enqueue(p->rchild);
        }
    }
}
void inthread(bitree *p)//add thread for bitree
{
    if (p != NULL)
    {
        inthread(p->lchild);

        if (p->lchild == NULL) { p->ltag = 1; }
        else p->ltag = 0;
        if (p->rchild == NULL) { p->rtag = 1; }
        else p->rtag = 0;
        if (pre != NULL)//就是为没有两个孩子的节点找到前趋和后继
        {
            if (pre->rtag == 1) { pre->rchild = p; }
            if (p->ltag == 1) { p->lchild = pre; }
        }
        pre = p;
        inthread(p->rchild);
    }

}
bitree* inordernext(bitree*p)//find next bitree node,this way is good
{
    bitree *q;
    if (p->rtag == 1)return p->rchild;
    else
    {
        q = p->rchild;
        while (q->ltag == 0)q = q->lchild;
        return q;
    }
}
void inorderb1(bitree *p)  /*后序非遍历二叉树的递归算法*/
{
    bitree* q, *root1;//root1 记录下根节点位置
    root1 = p;
    if (p != NULL)
    {

        while (p->ltag == 0) { p = p->lchild; }
        do
        {
            if (p != root1) printf("%4d", p->data);
            if (p->rtag == 1) { p = p->rchild; }
            else
            {
                q = p->rchild;
                while (q->ltag == 0) { q = q->lchild; }
                p = q;
            }
        } while (p != NULL);
        printf("%4d", root1->data);
        putchar(10);
    }
}
void inorderf1(bitree *p)  /*前序非遍历二叉树的递归算法*/
{
    bitree* q, *root1;//root1 记录下根节点位置
    root1 = p;
    if (p != NULL)
    {
        printf("%4d", root1->data);
        while (p->ltag == 0) { p = p->lchild; }
        do
        {
            if (p != root1) printf("%4d", p->data);
            if (p->rtag == 1) { p = p->rchild; }
            else
            {
                q = p->rchild;
                while (q->ltag == 0) { q = q->lchild; }
                p = q;
            }
        } while (p != NULL);

        putchar(10);
    }
}
void inorder1(bitree *p)  /*中序非遍历二叉树的递归算法*/
{
    bitree* q;
    if (p != NULL)
    {

        while (p->ltag == 0) { p = p->lchild; }
        do
        {
            printf("%4d", p->data);
            if (p->rtag == 1) { p = p->rchild; }
            else
            {
                q = p->rchild;
                while (q->ltag == 0) { q = q->lchild; }
                p = q;
            }
        } while (p != NULL);
        putchar(10);
    }
}
int main()   /*主函数*/
{
    bitree *root;
    root = creat();
    printf("\n中序:");
    inorder(root);
    printf("\n后序:");
    inorderb(root);
    printf("\n前序:");
    inorderf(root);
    putchar(10);
    inthread(root);
    printf("\n非遍历中序:");
    inorder1(root);
    printf("\n非遍历后序:");
    inorderb1(root);
    printf("\n非遍历前序:");
    inorderf1(root);
    return 0;
}
线索二叉树
#include<iostream>
using namespace std;
#define maxsize 100
typedef char datatype;
typedef struct node
{
	datatype data;
	int ltag, rtag;
	struct  node* lchild, *rchild;
}bitree;
bitree *Q[maxsize];
bitree *pre=NULL;
bitree* createbitree()//create bitree
{
	char ch;
	int fornt, rear;
	bitree *root, *s;
	fornt = 1;rear = 0;
	root = NULL;
	ch = getchar();
	while (ch != '\n')
	{
		s = NULL;
		if (ch != '@')
		{
			s = (bitree*)malloc(sizeof(bitree));
			s->data = ch;
			s->lchild = NULL;
			s->rchild = NULL;
		}
		rear++;
		Q[rear] = s;
		if (rear == 1) root = s;
		else 
		{
			if (s && Q[fornt])
				if (rear % 2 == 0)Q[fornt]->lchild = s;
				else Q[fornt]->rchild = s;
				if (rear % 2 == 1)fornt++;
		}
		ch=getchar();
	}
	return root;
}
bitree *inorderfornt(bitree *p)//find fornt bitree node
{
	bitree *q;
	if (p->ltag == 1)return p->lchild;
	else
	{
		q = p->lchild;
		while (q->rtag == 0)q = q->rchild;
		return q;
	}
}
bitree* inordernext(bitree*p)//find next bitree node,this way is good
{
	bitree *q;
	if (p->rtag == 1)return p->rchild;
	else
	{
		q = p->rchild;
		while (q->ltag == 0)q = q->lchild;
		return q;
	}
}

void insernode(bitree* add, bitree *p)//在双亲节点和右边的子节点进行插入新元素add,如果子左节点则相反就行
{
	bitree *s,*s1;
	s1 = p;
	int i = 1;
	int x;
	cout << "please input the location(insert in this node and right child): \n";
	cin >> x;
	if (s1 != NULL) { while (s1->ltag == 0) { s1 = s1->lchild; } }
	while (1)//进行插入操作
	{
		if (x == i)
		{
			
			s = inordernext(s1);
			add->ltag = 1;
			add->lchild = s1;
			add->rtag = s1->rtag;
			add->rchild = s1->rchild;

			s1->rtag = 0;
			s1->rchild = add;

			if (s != NULL&&s->ltag == 1)s->lchild = add;
			break;
		}
		s1 = inordernext(s1);i++;
	}
	
}
void display(bitree*s)
{
	if (s)
	{
		display(s->lchild);
		cout<< s->data;
		display(s->rchild);
	}

}
void inthread(bitree *p)//add thread for bitree
{
	if (p != NULL)
	{
		inthread(p->lchild);

		if (p->lchild == NULL) { p->ltag = 1; }
		else p->ltag = 0;
		if (p->rchild == NULL) { p->rtag = 1; }
		else p->rtag = 0;
		if (pre != NULL)//就是为没有两个孩子的节点找到前趋和后继
		{
			if (pre->rtag == 1) {pre->rchild = p; }
			if (p->ltag == 1) {p->lchild = pre; }
		}
		pre = p;
		inthread(p->rchild);
	}

}
void inorder(bitree*q)//display bitree
{
	if (q != NULL)
	{
		while (q->ltag == 0) { q = q->lchild; }
		do
		{
			cout << q->data;
			q = inordernext(q);
		} while (q != NULL);
		cout << endl;
	}
}
void main()
{
	bitree q,q1;
	int x;
	q = *createbitree();
	display(&q);cout << endl;
	inthread(&q);
	inorder(&q);
	cout << "please input you want to add element:\n";
	cin >> q1.data;
	insernode(&q1, &q);
	inorder(&q);

}
哈弗曼编码
#include<iostream>
#include<string>
#include <algorithm>  
using namespace std;
#define maxsize 100
typedef char datatype;
typedef struct
{

	float weight;
	int lchild, rchild, parent;
}hufmtree;
hufmtree T[maxsize];
int boot,nn;
void huffman()
{
	int n;
	int i, j, p1, p2;//记录最小的两个权重的下标值,p1第一小
	float small1, small2;
	cout << "please input the number of weigh:" << endl;cin >> n;
	nn = n;
	for (i = 0;i < maxsize;i++) { T[i].lchild = T[i].rchild = T[i].parent = 0; T[i].weight = 0.0; }//进行初始化
	for (i = 1;i <=n;i++) { cin >> T[i].weight; }//读入n个数的权值
	for (i = n+1;i < maxsize;i++)
	{
		p1= 0;
		p2 = 0;
		small1 = 1000.0;
		small2 = 1000.0;
		for (j = 1;j <i;j++)
		{
			//cout <<"date:"<<T[j].weight<<"\tparent:"<< T[j].parent<<" \t";
			if (T[j].parent == 0)
			{
				
				if (T[j].weight < small1)
				{
					small2 = small1;small1 = T[j].weight;p2 = p1;p1 = j;

				}
				else
				{
					if (T[j].weight < small2) { small2 = T[j].weight;p2 = j; }

				}
				//cout << "minor1:" << small1 << " \tminor2:" << small2<<endl;
				
			}

		}
		if (small2 == 1000)break;
		T[p1].parent = i;
		T[p2].parent = i ;
		T[i].lchild = p1 ;
		T[i].rchild = p2 ;
		T[i].weight = T[p1].weight + T[p2].weight;
	
		//cout << p1+1 << p2+1<<"  ";cout << T[i].weight;system("pause");
	}
	
	int x = 1;//为根节点位置赋值
	x = T[x].parent;
	while (T[x].parent != 0)
	{
		x = T[x].parent;
	}
	boot = x;
}
void humfcode(int num)
{
	int x=num;
	string code;
	x=T[x].parent;
	while (x != 0)
	{
		
		if (T[x].lchild == num) { code += "0"; }
		if (T[x].rchild == num) { code += "1"; }
		num = x;x = T[x].parent;
	}
	reverse(code.begin(), code.end());
	cout <<endl<< code;
}
void hufmdecode()
{
	int decode[maxsize];
	int x,i;
	x = boot;
	cout << "please input code(5  to stop):" << endl;
	for ( i = 0;i < maxsize;i++) 
	{ 
		cin >> decode[i];
		if (decode[i] == 5)break;
	}
	for (i = 0;i < maxsize;i++)
	{
		if (decode[i] == 0) { x = T[x].lchild; }
		else if (decode[i] == 1) { x = T[x].rchild; }
		else if (decode[i] == 5)break;
		
	}
	if (T[x].weight == 0) { cout << "Not find this element;" << endl; }
	else cout << "weight is:"<<T[x].weight << endl;

}
void displayhufm(int x)
{
	if (T[x].weight!=0)//节点的输入是从0开始的,所以以一个的输入读不出来,需要改进(曼哈树从1开始建立)
	{
		if(T[x].lchild!=0)displayhufm(T[x].lchild);
		cout << T[x].weight << "\t";
		if(T[x].rchild!=0)displayhufm(T[x].rchild);
	}
	
}
void main()
{
	int x;
	do
	{
		cout << "\t1.建立哈夫曼树。" << endl;
		cout << "\t2.输出哈夫曼树。" << endl;
		cout << "\t3.进行哈夫曼编码。" << endl;
		cout << "\t4.哈夫曼解码。" << endl;
		cout << "\t5.退出。" << endl;
		cout << "请选择:\n";
		cin >> x;
		switch (x)
		{
		case 1:huffman();break;
		case 2:displayhufm(boot);break;
		case 3: {for (int i = 1;i <=nn;i++) { cout << endl << T[i].weight << "的编码是:";humfcode(i); }cout << endl;break;}
		case 4: {hufmdecode();}
		}
		system("pause");
		system("cls");
	} while (x != 5);

}
 

转载于:https://www.cnblogs.com/zylg/p/9831850.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值