数据结构之树和二叉树

4 篇文章 0 订阅

十一，实现二叉树的各种基本运算的方法

#include<stdio.h>
#include<stdlib.h>
#define ElemType char
#define max 100
typedef struct node
{
ElemType data;
struct node *lchild;  //左孩子
struct node *rchild;  //右孩子
}BTNode;

void CreateTree(BTNode *&b, char *str)		//创建二叉树
{
BTNode *st[max];	//st数组作为顺序栈
BTNode *p;
int top = -1, k, j = 0;
char ch;
b = NULL;
ch = str[j];
while (ch != '\0')
{
switch (ch)
{
case '(':top++; st[top] = p; k = 1; break;
case ')':top--; break;
case ',':k = 2; break;
default:
{
p = (BTNode *)malloc(sizeof(BTNode));
p->data = ch;
p->lchild = NULL; p->rchild = NULL;
if (b == NULL)
b = p;
else
{
switch (k)
{
case 1:st[top]->lchild = p; break;
case 2:st[top]->rchild = p; break;
}
}
}

}
j++;
ch = str[j];
}
}

void destorytree(BTNode *&b)			//销毁二叉树
{
if (b != NULL)
{
destorytree(b->lchild);
destorytree(b->rchild);
free(b);
b = NULL;
}
//ClearBiTree();
}
void ClearBiTree(BTNode *T)			//清空
{
if(T == NULL)
return;
ClearBiTree(T->lchild);
ClearBiTree(T->rchild);
free(T);
}
BTNode *findnode(BTNode *b, ElemType e)			//查找结点
{
BTNode *p;
if (b == NULL)
return 0;
else if (b->data == e)
return b;
else
{
p = findnode(b->lchild, e);
if (p != NULL)
{
return p;
}
else
return findnode(b->rchild, e);

}
}

BTNode *Lchildnode(BTNode *p)		//找左孩子节点
{
return p->lchild;
}
BTNode *Rchildnode(BTNode *p)		//找右孩子节点
{
return p->rchild;
}

int height(BTNode *b)	        	//求高度
{
int lh, rh;
if (b == NULL)
return 0;
else
{
lh = height(b->lchild);
rh = height(b->rchild);
return(lh>rh) ? (lh+1 ): (rh+1);
}
}

void disptree(BTNode *b)
{
if (b != NULL)
{
printf("%c", b->data);
if (b->lchild != NULL || b->rchild != NULL)
{
printf("(");
disptree(b->lchild);
if (b->rchild != NULL)
printf(",");
disptree(b->rchild);
printf(")");

}
}

}
int main()
{
char c[100] = "A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))";
BTNode *b,*x,*y;
CreateTree(b, c);
printf("输出二叉树为：\n");
disptree(b);
printf("\n\nH的左节点为：\n");
x=Lchildnode(findnode(b,'H'));
disptree(x);
printf("\n\n右节点为:\n");
y=Rchildnode(findnode(b,'H'));
disptree(y);
printf("\n\n二叉树的高度为：%d",height(b));
printf("\n");
destorytree(b);ClearBiTree(b);
if(b==NULL)
printf("释放成功\n");
system("pause");
return 0;
}


十二，实现二叉树的各种遍历算法

#include<stdio.h>
#include<stdlib.h>
#define ElemType char
#define max 100
typedef struct node
{
ElemType data;
struct node *lchild;  //左孩子
struct node *rchild;  //右孩子
}BTNode;
typedef struct
{
BTNode * data[max];
int front, rear;
}SqQueue;

void CreateTree(BTNode *&b, char *str)		//创建二叉树
{
BTNode *st[max];	//st数组作为顺序栈
BTNode *p;
int top = -1, k, j = 0;
char ch;
b = NULL;
ch = str[j];
while (ch != '\0')
{
switch (ch)
{
case '(':top++; st[top] = p; k = 1; break;
case ')':top--; break;
case ',':k = 2; break;
default:
{
p = (BTNode *)malloc(sizeof(BTNode));
p->data = ch;
p->lchild = NULL; p->rchild = NULL;
if (b == NULL)
b = p;
else
{
switch (k)
{
case 1:st[top]->lchild = p; break;
case 2:st[top]->rchild = p; break;
}
}
}

}
j++;
ch = str[j];
}
}

void destorytree(BTNode *&b)			//销毁二叉树
{
if (b != NULL)
{
destorytree(b->lchild);
destorytree(b->rchild);
free(b);
b = NULL;
}
//ClearBiTree();
}
void ClearBiTree(BTNode *T)			//清空二叉树
{
if (T == NULL)
return;
ClearBiTree(T->lchild);
ClearBiTree(T->rchild);
free(T);
}

void disptree(BTNode *b)		//输出二叉树
{
if (b != NULL)
{
printf("%c", b->data);
if (b->lchild != NULL || b->rchild != NULL)
{
printf("(");
disptree(b->lchild);
if (b->rchild != NULL)
printf(",");
disptree(b->rchild);
printf(")");

}
}

}

void Preorder(BTNode *b)      //先序遍历递归算法(跟   左  右)
{
if (b != NULL)
{
printf("%4c", b->data);
Preorder(b->lchild);
Preorder(b->rchild);
}
}
void Inorder(BTNode *b)      //中序遍历递归算法(左  跟   右)
{
if (b != NULL)
{
Inorder(b->lchild);
printf("%4c", b->data);
Inorder(b->rchild);
}
}
void Postorder(BTNode *b)      //后序遍历递归算法(左  右   跟)
{
if (b != NULL)
{

Postorder(b->lchild);
Postorder(b->rchild);
printf("%4c", b->data);
}
}
void InitQueue(SqQueue *&q)
{
q = (SqQueue *)malloc(sizeof(SqQueue));
q->front = q->rear = 0;
}
void DestroyQueue(SqQueue *&q)
{
free(q);
}
bool emptyQueue(SqQueue *q)
{
return(q->front == q->rear);
}
//进队列
bool enQueue(SqQueue * &q,BTNode * &b)
{
if(q->rear==max-1)
{
return false;
}
q->rear++;
q->data[q->rear]=b;
return true;
}

//出队列
bool deQueue(SqQueue * &q,BTNode * &b)
{
if(q->front==q->rear)
{
return false;
}
q->front++;
b=q->data[q->front];
return true;
}

void levelOrder(BTNode * &b)		//层次遍历
{
SqQueue *q;
InitQueue(q);
if(b!=NULL)
{
enQueue(q,b);
}
while(emptyQueue(q)!=true)
{
deQueue(q,b);
printf("%4c",b->data);
if(b->lchild!=NULL)
{
enQueue(q,b->lchild);
}
if(b->rchild!=NULL)
{
enQueue(q,b->rchild);
}
}
}

int main()
{
int n;
char c[100] = "A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))";
BTNode *b;
CreateTree(b, c);
printf("输出二叉树为：\n");
disptree(b);
printf("\n输入你要进行的操作\n1.    先序排列\n2.    中序排列\n3.    后序排列\n4.    层次排列\n");
while (scanf("%d", &n))
{

switch (n)
{
case 1:
Preorder(b);
printf("\n");
break;
case 2:
Inorder(b);	printf("\n");
break;

case 3:
Postorder(b); printf("\n");
break;
case 4:levelOrder(b); printf("\n");
break;

}
}
destorytree(b); ClearBiTree(b);
if (b == NULL)
printf("释放成功\n");
system("pause");
return 0;
}


十三，由遍历序列构造二叉树

#include<stdio.h>
#include<stdlib.h>
#define ElemType char
#define max 100
typedef struct node
{
ElemType data;
struct node *lchild;  //左孩子
struct node *rchild;  //右孩子
}BTNode;

void CreateTree(BTNode *&b, char *str)		//创建二叉树
{
BTNode *st[max];	//st数组作为顺序栈
BTNode *p;
int top = -1, k, j = 0;
char ch;
b = NULL;
ch = str[j];
while (ch != '\0')
{
switch (ch)
{
case '(':top++; st[top] = p; k = 1; break;
case ')':top--; break;
case ',':k = 2; break;
default:
{
p = (BTNode *)malloc(sizeof(BTNode));
p->data = ch;
p->lchild = NULL; p->rchild = NULL;
if (b == NULL)
b = p;
else
{
switch (k)
{
case 1:st[top]->lchild = p; break;
case 2:st[top]->rchild = p; break;
}
}
}

}
j++;
ch = str[j];
}
}

void destorytree(BTNode *&b)			//销毁二叉树
{
if (b != NULL)
{
destorytree(b->lchild);
destorytree(b->rchild);
free(b);
b = NULL;
}
//ClearBiTree();
}
void ClearBiTree(BTNode *T)			//清空二叉树
{
if(T == NULL)
return;
ClearBiTree(T->lchild);
ClearBiTree(T->rchild);
free(T);
}

void disptree(BTNode *b)		//输出二叉树
{
if (b != NULL)
{
printf("%c", b->data);
if (b->lchild != NULL || b->rchild != NULL)
{
printf("(");
disptree(b->lchild);
if (b->rchild != NULL)
printf(",");
disptree(b->rchild);
printf(")");
}
}

}

BTNode *CreateBT1(char *pre,char *in,int n)   		//先序和中序
{
BTNode *b;
char *p;
int k;
if(n<=0)
return NULL;
b=(BTNode *)malloc(sizeof(BTNode));
b->data=*pre;
for(p=in;p<in+n;p++)
{
if(*p==*pre)
break;
}
k=p-in;
b->lchild=CreateBT1(pre+1,in,k);
b->rchild=CreateBT1(pre+k+1,p+1,n-k-1);
return b;

}
BTNode * CreateBT2( char * post, char * in, int n )
{
BTNode	* b;
char	r, *p;
int	k;
if ( n <= 0 )
return(NULL);
r	= *(post + n - 1);
b	= (BTNode *) malloc( sizeof(BTNode) );
b->data = r;
for ( p = in; p < in + n; p++ )
if ( *p == r )
break;
k		= p - in;
b->lchild	= CreateBT2( post, in, k );
b->rchild	= CreateBT2( post + k, p + 1, n - k - 1 );
return(b);
}

int main()
{
int n;
char c1[100]="ABDEHJKLMNCFGI";
char c2[100]="DBJHLKMNEAFCGI";
char c3[100]="DJLNMKHEBFIGCA";
BTNode *b;
BTNode *x;

printf("\n输入你要进行的操作\n1.   先序和中序输出\n2.   中序和后序输出\n");
while(scanf("%d",&n))
{
switch(n)
{
case 1:
b=CreateBT1(c1,c2,14);
printf("先序为：%s\n",c1);
printf("中序为：%s\n",c2);
printf("输出二叉树为：\n");
disptree(b);
printf("\n");
break;
case 2:
{

printf("中序为：%s\n",c2);
printf("后序为：%s\n",c3);
x=CreateBT2(c3,c2,14);
printf("输出二叉树为：\n");
disptree(x);
printf("\n");
break;
}

}
}
destorytree(b);ClearBiTree(b);
if(b==NULL)
printf("释放成功\n");
system("pause");
return 0;
}


十四，构造哈夫曼树和生成哈夫曼编码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N (50)      // 树中叶子结点数最大值
#define M (2 * N - 1) // 树中结点总数最大值

typedef struct
{
char data[5]; // 结点值
int weight; // 权重
int parent; // 双亲结点
int lchild; // 左孩子结点
int rchild; // 右孩子结点
}HTNode; // 声明哈夫曼树结点类型

typedef struct
{
char cd[N]; // 存放哈夫曼编码
int start;
}HCode; // 声明哈夫曼编码类型

/*-------------由含有n个叶子结点的ht构造完整的哈夫曼树-----------------*/
void create_huffman_tree(HTNode ht[], int n)
{
int i;
int k;
int lnode;
int rnode;
int min1;
int min2;

// 所有结点的相关域设置初值为-1
for (i = 0; i < 2 * n - 1; i++)
ht[i].parent = ht[i].lchild = ht[i].rchild = -1;
for (i = n; i < 2 * n - 1; i++) // 构造哈夫曼树的分支结点
{
min1 = min2 = 32767;
lnode = rnode = -1;
for (k = 0; k <= i - 1; k++) // 查找最小和次小的结点
{
if (ht[k].parent == -1) // 只在尚未构造二叉树的结点中查找
{
if (ht[k].weight < min1)
{
min2 = min1;
rnode = lnode;
min1 = ht[k].weight;
lnode = k;
}
else if (ht[k].weight < min2)
{
min2 = ht[k].weight;
rnode = k;
}
}
}
ht[lnode].parent = i; // 合并两个最小和次小的结点
ht[rnode].parent = i;
ht[i].weight = ht[lnode].weight + ht[rnode].weight; // 计算双亲结点的权重
ht[i].lchild = lnode; // 设置双亲结点的左孩子
ht[i].rchild = rnode; // 设置双亲结点的右孩子
}
}

/*-------------由哈夫曼树ht构造哈夫曼编码hcd-----------------*/
void create_huffman_code(HTNode ht[], HCode hcd[], int n)
{
int i;
int f;
int c;
HCode hc;

for (i = 0; i < n; i++) // 根据哈夫曼树构造所有叶子结点的哈夫曼编码
{
hc.start = n;
c = i;
f = ht[i].parent;
while (f != -1) // 循环直到树根结点
{
if (ht[f].lchild == c) // 处理左孩子结点
hc.cd[hc.start--] = '0';
else // 处理右孩子结点
hc.cd[hc.start--] = '1';
c = f;
f = ht[f].parent;
}
hc.start++; // start指向哈夫曼编码最开始字符
hcd[i] = hc;
}
}

/*-------------输出哈夫曼编码-----------------*/
void display_huffman_code(HTNode ht[], HCode hcd[], int n)
{
int i;
int k;
int sum = 0;
int m = 0;
int j;

printf("输出哈夫曼编码:\n");
for (i = 0; i < n; i++)
{
j = 0;
printf("    %s:\t", ht[i].data);
for (k = hcd[i].start; k <= n; k++)
{
printf("%c", hcd[i].cd[k]);
j++;
}
m += ht[i].weight;
sum += ht[i].weight * j;
printf("\n");
}

printf("\n平均长度 = %g\n", 1.0 * sum / m);
}

int main()
{
int n = 15;
int i;
HTNode ht[M];
HCode hcd[N];
char *str[] = { "The", "of", "a", "to", "and", "in", "that", "he", "is", "at", "on", "for", "His", "are", "be" };
int fnum[] = { 1192, 677, 541, 518, 462, 450, 242, 195, 190, 181, 174, 157, 138, 124, 123 };

for (i = 0; i < n; i++)
{
strcpy(ht[i].data, str[i]);
ht[i].weight = fnum[i];
}
create_huffman_tree(ht, n); // 创建哈夫曼树
create_huffman_code(ht, hcd, n); // 构造哈夫曼编码
display_huffman_code(ht, hcd, n); // 输出哈夫曼编码

system("pause");
return 0;
}


• 0
点赞
• 1
收藏
觉得还不错? 一键收藏
• 0
评论
10-29 1049
08-10 1万+
11-19 173
08-25 4176
10-08 2185
02-21 2377
09-07 791
09-12 127
09-12 169
09-09 953

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