树与二叉树

5.1 二叉树

5.1.1 二叉树的定义

每个结点的度都不大于2,且孩子结点次序不能任意颠倒的树称为二叉树

5.1.2 二叉树的性质

1).在二叉树的第i层上至多有2i-1个结点
2).深度为k的二叉树至多有2k-1个结点
3).若终端结点数为n0,而度数为二的结点数为n2,则n0=n2+1
4).具有n个结点的完全二叉树的深度为 ⌊ l o g 2 n ⌋ + 1 \left \lfloor log_2n \right \rfloor+1 log2n+1
5).对具有n个结点的完全二叉树,对序号为i的结点有:
\quad 若i=1,则序号为i的结点是根节点,无双亲结点;若i>1,则结点的双亲节点序号为 ⌊ i / 2 ⌋ \left \lfloor i/2 \right\rfloor i/2
\quad 若2i>n,则序号为i的结点无左孩子;若<=,则序号为i的结点的左孩子结点的序号为2i
\quad 若2i+1>n,则序号为i的结点无右孩子;若<=,则序号为i的结点的右孩子结点序号为2i+1

5.1.3 二叉树的存储结构

顺序存储结构:适用于完全二叉树
链式存储结构:

typedef char ElemType;
typedef struct Node
{
	ElemType e;
	struct Node * Lchild;
	struct Node * Rchild;
}BiTNode,* Bitree;
5.1.4 二叉树的创建和遍历
\\"SeqStack.cpp" 
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAXSIZE 50
typedef char ElemType;
typedef struct Node
{
	ElemType e;
	struct Node * Lchild;
	struct Node * Rchild;
}BiTNode,* Bitree;
typedef struct
{
	BiTNode *elem[MAXSIZE];
	int top;
}SeqStack;
void InitStack(SeqStack *S)//初始化 
{
	S->top=-1;
}
int IsEmpty(SeqStack S)//判栈空函数 
{
	if(S.top==-1) return true;
	else 
		return false;	
}
int IsFull(SeqStack S)//判栈满函数 
{
	if(S.top==MAXSIZE-1) return true;
	else 
		return false;	
}
int Push(SeqStack *S,BiTNode *x)//在S顶部插入元素x 
{
	if(IsFull(*S)) return false;
	S->elem[++S->top]=x;
	return true;
}
int Pop(SeqStack *S,BiTNode  **x)//删除栈S顶部元素 
{
	if(IsEmpty(*S)) return false;
	(*x)=S->elem[S->top--];
	return true;
}
int GeTop(SeqStack S,BiTNode  **x)
{
	if(IsEmpty(S)) return false;
	(*x)=S.elem[S.top];
	return true;	
}
\\"SeqQueue.cpp" 
#include"SeqStack.cpp" 
typedef char ElemType;
typedef struct 
{
	BiTNode * elem[MAXSIZE];
	int front;
	int rear;
}SeqQueue;

int InitQueue(SeqQueue *Q)//初始化队列 
{
	Q->front=Q->rear=0;
}
int IsEmpty(SeqQueue Q)//判断队列空 
{
	if(Q.front==Q.rear) return true;
	else 
		return 	false;
} 
int EnterQueue(SeqQueue *Q,BiTNode *x)//队尾插入x 
{
	if((Q->rear+1)%MAXSIZE==Q->front) return false;
	Q->elem[Q->rear]=x;
	Q->rear=(Q->rear+1)%MAXSIZE;
	return true;
} 
int DeleteQueue(SeqQueue *Q,BiTNode **x)//队头元素出队 
{
	if(IsEmpty(*Q)) return false;
	(*x)=Q->elem[Q->front];
	Q->front=(Q->front+1)%MAXSIZE;
	return true;
} 
int GetHead(SeqQueue Q,BiTNode **x)//取队头元素
{
	if(IsEmpty(Q)) return false;
	(*x)=Q.elem[Q.front];
	return true;
} 
#include"SeqQueue.cpp" 

void Initiate(Bitree *bt)//初始化二叉树 
{
	* bt=(Bitree)malloc(sizeof(BiTNode));
	(* bt)->Lchild=(* bt)->Rchild=NULL;
}
void InCreate(Bitree *bt)//先序遍历创建二叉树 
{
	char ch;
	ch=getchar();
	if(ch=='.') 
		* bt=NULL;
	else
	{
		* bt=(Bitree)malloc(sizeof(BiTNode));
		(* bt)->e=ch;
		InCreate(&((*bt)->Lchild));
		InCreate(&((*bt)->Rchild));	
	}
}
int IsEmpty(Bitree bt)//判断二叉树为空 
{
	if(bt->Lchild==NULL && bt->Rchild==NULL)
		return true;
	else return false;
}
void Visit(ElemType e)//访问二叉树的节点 
{
	printf("%c",e);
}
void PreOrder(Bitree root)//递归先序遍历二叉树 
{
	if(root!=NULL)
	{
		Visit(root->e);
		PreOrder(root->Lchild);
		PreOrder(root->Rchild);
	}
}
void InOrder(Bitree root)//递归中序遍历二叉树 
{
	if(root!=NULL)
	{
		InOrder(root->Lchild);
		Visit(root->e);
		InOrder(root->Rchild);
	}
}
void PostOrder(Bitree root)//递归后序遍历二叉树 
{
	if(root!=NULL)
	{
		PostOrder(root->Lchild);
		PostOrder(root->Rchild);
		Visit(root->e);
	}
}

void StackPreOrder(Bitree root)//基于栈的先序遍历 
{
	SeqStack S;
	InitStack(&S);
    BiTNode * p = root;
    while(p!=NULL||!IsEmpty(S))
	{
        if(p)
		{
            Push(&S,p);
            Visit(p->e); 
            p = p->Lchild;
        }
		else
		{
            Pop(&S,&p);
            p = p->Rchild;
        }
    }
}
void StackInOrder(Bitree root)//基于栈的中序遍历 
{
	SeqStack S;
	InitStack(&S);
    BiTNode * p = root;
	while(p!=NULL || !IsEmpty(S))
	{
		if(p)
		{
			Push(&S,p);
			p=p->Lchild;
		}
		else
		{
			Pop(&S,&p);
			Visit(p->e);
			p=p->Rchild;
		}
	}
}
void StackPostOrder(Bitree root)//基于栈的后序遍历 
{
	BiTNode *p,*q;
	p=root,q=NULL;
	SeqStack S;
	InitStack(&S);
	while(p!=NULL || !IsEmpty(S))
	{
		if(p!=NULL)
		{
			Push(&S,p);
			p=p->Lchild;
		}
		else
		{
			GeTop(S,&p);
			if((p->Rchild==NULL) || (p->Rchild==q))
			{
				Visit(p->e);
				q=p;
				Pop(&S,&p);
				p=NULL;
			}
			else
			{
				p=p->Rchild;
			}
		}
	}
} 
void LevelTraversal(Bitree root)//层序遍历
{
    SeqQueue Q;
    BiTNode *p;
	InitQueue(&Q);    //队列的初始化
    EnterQueue(&Q,p);  //入队
    while(!IsEmpty(Q))//队列空,遍历结束
    {
        DeleteQueue(&Q,&p);//出队打印
        printf("%c",p->e);
        if(p->Lchild!= NULL)
        {
        	EnterQueue(&Q,p->Lchild);
        }
        if(p->Rchild != NULL)
        {
            EnterQueue(&Q,p->Rchild);
        }
    }
}
int main()
{
	Bitree bt,root;	
	Initiate(&bt);
	printf("请输入你想要创建的二叉树(按先序):");
	InCreate(&bt);
	root=bt;
	printf("先序遍历二叉树:"); 
	PreOrder(root);
	printf("\n中序遍历二叉树:");
	InOrder(root);
	printf("\n后序遍历二叉树:");
	PostOrder(root);
	printf("\n基于栈的先序遍历:");
	StackPreOrder(root); 
	printf("\n基于栈的中序遍历:");
	StackInOrder(root);
	printf("\n基于栈的后序遍历:");
	StackPostOrder(root);
	printf("\n层序遍历");
    LevelTraversal(root); 
	return 0;
}
5.1.5 线索二叉树

5.2 树与森林的遍历

5.2.1 树的遍历

先根遍历:对应转换后二叉树的前序遍历。
\quad\quad\quad\quad 1.访问根结点
\quad\quad\quad\quad 2.从左到右,依次先根遍历根结点的每一棵子树
后根遍历:对应转换后二叉树的中序遍历。
\quad\quad\quad\quad 1.从左到右,依次后根遍历根结点的每一棵子树
\quad\quad\quad\quad 2.访问根结点

5.2.2 森林的遍历

先序遍历
\quad\quad\quad\quad 1.访问森林中第一棵树的根节点
\quad\quad\quad\quad 2.先序遍历第一棵树的根节点的子树森林
\quad\quad\quad\quad 3.先序遍历除去第一棵树后剩余的树构成的森林
中序遍历
\quad\quad\quad\quad 1.中序遍历森林中第一棵树的根节点的子树森林
\quad\quad\quad\quad 2.访问第一棵树的根结点
\quad\quad\quad\quad 3.中序遍历除去第一棵树之后剩余的树构成的森林
后序遍历
\quad\quad\quad\quad 1.后序遍历森林中第一棵树的根节点的子树森林
\quad\quad\quad\quad 2.后序遍历除去第一棵树之后剩余的树构成的森林
\quad\quad\quad\quad 3.访问第一棵树的根结点

5.3 哈夫曼树

//哈夫曼树的创建及哈夫曼编码的生成 
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 20//叶子结点的最大数量 
#define M 2*N-1// 全部结点的最大数量 
typedef char * HuffmanCode[N+1];
typedef struct
{
	int weight;
	int Parent;
	int Lchild;
	int Rchild;
}HTNode,HuffmanTree[M+1];
//在ht[1]-ht[i]范围内选两个parent为0,且权值最小的结点,并把序号赋值给s1,s2 
void select(HuffmanTree ht,int i,int &s1,int &s2)
{
	int w1=100,w2=100;
	int j,k;
	for(j=1;j<=i;j++)
		if((ht[j].Parent==0) && (ht[j].weight<w1))
		{
			s1=j;
			w1=ht[j].weight;
		}
	for(k=1;k<=i;k++)
		if((ht[k].Parent==0) && (ht[k].weight<w2) && (k!=s1))
		{
			s2=k;			
			w2=ht[k].weight;
		}
}

void CrtHuffmantree(HuffmanTree ht,int w[],int n)//建立哈弗曼树 
{
	int i,m;
	int s1,s2;
	m=2 * n-1;
	for(i=1;i<=n;i++)	ht[i]={w[i],0,0,0};
	for(i=n+1;i<=m;i++)	ht[i]={0,0,0,0};
	for(i=n+1;i<=m;i++)//创建非叶结点 
	{
		select(ht,i-1,s1,s2);
		ht[i].weight=ht[s1].weight+ht[s2].weight;
		ht[s1].Parent=i,ht[s2].Parent=i;
		ht[i].Lchild=s1,ht[i].Rchild=s2;
	}
}
void Visit(HuffmanTree ht,int m)//访问哈弗曼树 
{
	int i;
	printf("weight   parent   Lchild   Rchild\n");
	for(i=1;i<=m;i++)
	{
		printf("%3d%9d%9d%10d\n",ht[i].weight,ht[i].Parent,ht[i].Lchild,ht[i].Rchild);
	}
}
void CrtHuffmanCode(HuffmanTree ht,HuffmanCode hc,int n)
{
	int i,j,start,c,p;
	char * cd;
	cd=(char * )malloc(n*sizeof(char));
	cd[n-1]='\0';
	for(i=1;i<=n;i++)
	{
		start=n-1;
		c=i;
		p=ht[i].Parent;
		while(p!=0)
		{
			start--;
			if(ht[p].Lchild==c)	
			{
				cd[start]='0';
			}
			else 
			{
				cd[start]='1';
			}
			c=p,p=ht[p].Parent;
		}
		hc[i]=(char *)malloc((n-start)*sizeof(char));
		strcpy(hc[i],&cd[start]);

		printf("%d的编码为:",ht[i].weight);
		while(start!=n-1)
		{
			printf("%c",cd[start]);
			start++;
		}
		printf("\n");//打印ht[i]问题 
	}
	free(cd);
}
int main()
{
	int n,m,i;
	HuffmanTree ht;
	HuffmanCode hc;
	printf("请输入你想要创建哈弗曼树叶子结点的数量:");
	scanf("%d",&n);
	m=2*n-1;//定义完n再m 
	int w[n+1];
	printf("请输入你想要创建哈弗曼树的权值:");
	for(i=1;i<=n;i++)
		scanf("%d",&w[i]);
	CrtHuffmantree(ht,w,n);
	printf("\nHuffmantree:\n");
	Visit(ht,m);
	CrtHuffmanCode(ht,hc,n);
	return 0;	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值