1.树的储存方式
//****************双亲表示法************************
#define Max_TREE_SIZE 100
typedef int TElemType;
typedef struct PTNode //结点结构
{
TElemType data;
int parent;
}PTNode;
typedef struct
{
PTNode nodes[Max_TREE_SIZE];//结点数组
int r,n;
}Ptree;
//****************孩子表示法************************
typedef struct CTNode //孩子结点
{
int child;
struct CTNode *next;
}*ChildPtr;
typedef struct //表头结构
{
TElemType data;
ChildPtr firstChild;
}CTBox;
typedef struct
{
CTBox nodes[Max_TREE_SIZE]; //结点数组
int r,n;
}CTree;
//****************双亲孩子表示法************************
typedef struct CTNode
{
int child;
struct CTNode *next;
}*ChildPtr;
typedef struct
{
TElemType data;
int parent;
ChildPtr firstChild;
}CTBox;
typedef struct
{
CTBox nodes[Max_TREE_SIZE];
int r,n;
}CTree;
59
1
//****************双亲表示法************************
2
3
typedef int TElemType;
4
typedef struct PTNode //结点结构
5
{
6
TElemType data;
7
int parent;
8
}PTNode;
9
10
typedef struct
11
{
12
PTNode nodes[Max_TREE_SIZE];//结点数组
13
int r,n;
14
}Ptree;
15
16
17
//****************孩子表示法************************
18
typedef struct CTNode //孩子结点
19
{
20
int child;
21
struct CTNode *next;
22
}*ChildPtr;
23
24
typedef struct //表头结构
25
{
26
TElemType data;
27
ChildPtr firstChild;
28
}CTBox;
29
30
31
typedef struct
32
{
33
CTBox nodes[Max_TREE_SIZE]; //结点数组
34
int r,n;
35
}CTree;
36
37
38
39
//****************双亲孩子表示法************************
40
41
typedef struct CTNode
42
{
43
int child;
44
struct CTNode *next;
45
}*ChildPtr;
46
47
typedef struct
48
{
49
TElemType data;
50
int parent;
51
ChildPtr firstChild;
52
}CTBox;
53
54
typedef struct
55
{
56
CTBox nodes[Max_TREE_SIZE];
57
int r,n;
58
}CTree;
59
2.根据扩展前序列确定一个二叉树(通过外界持续输入字符串或者是以字符串的形式输入)
//**************************BiTree.h*******************************
#ifndef BITREE_H
#define BITREE_H
#include <stdio.h>
#include <stdlib.h>
typedef int datatype;
typedef struct Tree
{
datatype data;
struct Tree *left;
struct Tree *right;
}Node,*BiTree;
//以输入扩展前序递归的方式创建二叉树
void CreateBiTree(BiTree *T);
//后序遍历
void NextOrderTravel(BiTree T);
#endif //BITREE_H
//**************************BiTree.c*******************************
#include "BiTree.h"
//以输入扩展前序递归的方式创建二叉树
void CreateBiTree(BiTree *T)
{
char ch;
scanf("%c",&ch);
if('#' == ch)
{
*T = NULL;
}
else
{
*T = (BiTree)malloc(sizeof(Node));
(*T)->data = ch;
CreateBiTree(&(*T)->left);
CreateBiTree(&(*T)->right);
}
}
void NextOrderTravel(BiTree T)
{
if(NULL == T)return;
NextOrderTravel(T->left);
NextOrderTravel(T->right);
printf("%c ",T->data);
}
//**************************BiTreeTest.c*******************************
#include <stdio.h>
#include "BiTree.h"
char *str;
void CreateBiTreeStr(BiTree *T)
{
char ch = *str++;
if('#' == ch)
{
*T = NULL;
}
else
{
*T = (BiTree)malloc(sizeof(Node));
(*T)->data = ch;
CreateBiTreeStr(&(*T)->left);
CreateBiTreeStr(&(*T)->right);
}
}
//将这个序列以字符串的形式输入函数生成二叉树
void Create(BiTree *T,char *str1)
{
str = str1;
CreateBiTreeStr(T);
}
int main()
{
BiTree T = NULL;
CreateBiTree(&T);
NextOrderTravel(T);
printf("
-------
");
char *str1 = "AB#D##C##";
Create(&T,str1);
NextOrderTravel(T);
}
x
1
//**************************BiTree.h*******************************
2
3
4
5
6
7
8
typedef int datatype;
9
10
typedef struct Tree
11
{
12
datatype data;
13
struct Tree *left;
14
struct Tree *right;
15
}Node,*BiTree;
16
17
18
//以输入扩展前序递归的方式创建二叉树
19
void CreateBiTree(BiTree *T);
20
21
//后序遍历
22
void NextOrderTravel(BiTree T);
23
24
25
26
//BITREE_H
27
28
29
//**************************BiTree.c*******************************
30
31
32
33
//以输入扩展前序递归的方式创建二叉树
34
void CreateBiTree(BiTree *T)
35
{
36
char ch;
37
scanf("%c",&ch);
38
39
if('#' == ch)
40
{
41
*T = NULL;
42
}
43
else
44
{
45
*T = (BiTree)malloc(sizeof(Node));
46
(*T)->data = ch;
47
CreateBiTree(&(*T)->left);
48
CreateBiTree(&(*T)->right);
49
}
50
}
51
52
void NextOrderTravel(BiTree T)
53
{
54
if(NULL == T)return;
55
56
NextOrderTravel(T->left);
57
NextOrderTravel(T->right);
58
59
printf("%c ",T->data);
60
}
61
62
63
//**************************BiTreeTest.c*******************************
64
65
66
67
char *str;
68
69
void CreateBiTreeStr(BiTree *T)
70
{
71
72
char ch = *str++;
73
74
if('#' == ch)
75
{
76
*T = NULL;
77
}
78
else
79
{
80
*T = (BiTree)malloc(sizeof(Node));
81
(*T)->data = ch;
82
CreateBiTreeStr(&(*T)->left);
83
CreateBiTreeStr(&(*T)->right);
84
}
85
}
86
87
//将这个序列以字符串的形式输入函数生成二叉树
88
void Create(BiTree *T,char *str1)
89
{
90
str = str1;
91
CreateBiTreeStr(T);
92
}
93
94
int main()
95
{
96
BiTree T = NULL;
97
CreateBiTree(&T);
98
NextOrderTravel(T);
99
100
printf("
-------
");
101
102
103
char *str1 = "AB#D##C##";
104
Create(&T,str1);
105
106
NextOrderTravel(T);
107
}
3.线索二叉树的建立,线索化,遍历
#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
// 线索存储标志位
// Link(0):表示指向左右孩子的指针
// Thread(1):表示指向前驱后继的线索
typedef enum {Link, Thread} PointerTag;
typedef struct BiThrNode
{
char data;
struct BiThrNode *lchild, *rchild;
PointerTag ltag;
PointerTag rtag;
} BiThrNode, *BiThrTree;
// 全局变量,始终指向刚刚访问过的结点
BiThrTree pre;
// 创建一棵二叉树,约定用户遵照前序遍历的方式输入数据
void CreateBiThrTree( BiThrTree *T )
{
char c;
scanf("%c", &c);
if( '#' == c )
{
*T = NULL;
}
else
{
*T = (BiThrNode *)malloc(sizeof(BiThrNode));
(*T)->data = c;
(*T)->ltag = Link;
(*T)->rtag = Link;
CreateBiThrTree(&(*T)->lchild);
CreateBiThrTree(&(*T)->rchild);
}
}
// 中序遍历线索化
void InThreading(BiThrTree T)
{
if( T )
{
InThreading( T->lchild ); // 递归左孩子线索化
if( !T->lchild ) // 如果该结点没有左孩子,设置ltag为Thread,并把lchild指向刚刚访问的结点。
{
T->ltag = Thread;
T->lchild = pre;
}
if( !pre->rchild )
{
pre->rtag = Thread;
pre->rchild = T;
}
pre = T;
InThreading( T->rchild ); // 递归右孩子线索化
}
}
void InOrderThreading( BiThrTree *p, BiThrTree T )
{
*p = (BiThrTree)malloc(sizeof(BiThrNode));
(*p)->ltag = Link;
(*p)->rtag = Thread;
(*p)->rchild = *p;
if( !T )
{
(*p)->lchild = *p;
}
else
{
(*p)->lchild = T;
pre = *p;
InThreading(T);
pre->rchild = *p;
pre->rtag = Thread;
(*p)->rchild = pre;
}
}
void visit( char c )
{
printf("%c", c);
}
// 中序遍历二叉树,非递归
void InOrderTraverse( BiThrTree T )
{
BiThrTree p;
p = T->lchild;
while( p != T )
{
while( p->ltag == Link )
{
p = p->lchild;
}
visit(p->data);
while( p->rtag == Thread && p->rchild != T )
{
p = p->rchild;
visit(p->data);
}
p = p->rchild;
}
}
int main()
{
BiThrTree P, T = NULL;
CreateBiThrTree( &T );
InOrderThreading( &P, T );
printf("中序遍历输出结果为: ");
InOrderTraverse( P );
printf("
");
return 0;
}
1
134
1
2
3
4
typedef char ElemType;
5
6
// 线索存储标志位
7
// Link(0):表示指向左右孩子的指针
8
// Thread(1):表示指向前驱后继的线索
9
typedef enum {Link, Thread} PointerTag;
10
11
typedef struct BiThrNode
12
{
13
char data;
14
struct BiThrNode *lchild, *rchild;
15
PointerTag ltag;
16
PointerTag rtag;
17
} BiThrNode, *BiThrTree;
18
19
// 全局变量,始终指向刚刚访问过的结点
20
BiThrTree pre;
21
22
// 创建一棵二叉树,约定用户遵照前序遍历的方式输入数据
23
void CreateBiThrTree( BiThrTree *T )
24
{
25
char c;
26
27
scanf("%c", &c);
28
if( '#' == c )
29
{
30
*T = NULL;
31
}
32
else
33
{
34
*T = (BiThrNode *)malloc(sizeof(BiThrNode));
35
(*T)->data = c;
36
(*T)->ltag = Link;
37
(*T)->rtag = Link;
38
39
CreateBiThrTree(&(*T)->lchild);
40
CreateBiThrTree(&(*T)->rchild);
41
}
42
}
43
44
// 中序遍历线索化
45
void InThreading(BiThrTree T)
46
{
47
if( T )
48
{
49
InThreading( T->lchild ); // 递归左孩子线索化
50
51
if( !T->lchild ) // 如果该结点没有左孩子,设置ltag为Thread,并把lchild指向刚刚访问的结点。
52
{
53
T->ltag = Thread;
54
T->lchild = pre;
55
}
56
57
if( !pre->rchild )
58
{
59
pre->rtag = Thread;
60
pre->rchild = T;
61
}
62
63
pre = T;
64
65
InThreading( T->rchild ); // 递归右孩子线索化
66
}
67
}
68
69
void InOrderThreading( BiThrTree *p, BiThrTree T )
70
{
71
*p = (BiThrTree)malloc(sizeof(BiThrNode));
72
(*p)->ltag = Link;
73
(*p)->rtag = Thread;
74
(*p)->rchild = *p;
75
if( !T )
76
{
77
(*p)->lchild = *p;
78
}
79
else
80
{
81
(*p)->lchild = T;
82
pre = *p;
83
InThreading(T);
84
pre->rchild = *p;
85
pre->rtag = Thread;
86
(*p)->rchild = pre;
87
}
88
}
89
90
void visit( char c )
91
{
92
printf("%c", c);
93
}
94
95
// 中序遍历二叉树,非递归
96
void InOrderTraverse( BiThrTree T )
97
{
98
BiThrTree p;
99
p = T->lchild;
100
101
while( p != T )
102
{
103
while( p->ltag == Link )
104
{
105
p = p->lchild;
106
}
107
visit(p->data);
108
109
while( p->rtag == Thread && p->rchild != T )
110
{
111
p = p->rchild;
112
visit(p->data);
113
}
114
115
p = p->rchild;
116
}
117
}
118
119
int main()
120
{
121
BiThrTree P, T = NULL;
122
123
CreateBiThrTree( &T );
124
125
InOrderThreading( &P, T );
126
127
printf("中序遍历输出结果为: ");
128
129
InOrderTraverse( P );
130
131
printf("
");
132
133
return 0;
134
}
3.赫夫曼树的建立
#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
struct BTreeNode
{
ElemType data;
struct BTreeNode* left;
struct BTreeNode* right;
};
//1、输出二叉树,可在前序遍历的基础上修改。采用广义表格式,元素类型为int
void PrintBTree_int(struct BTreeNode* BT)
{
if (BT != NULL)
{
printf("%d", BT->data); //输出根结点的值
if (BT->left != NULL || BT->right != NULL)
{
printf("(");
PrintBTree_int(BT->left); //输出左子树
if (BT->right != NULL)
printf(",");
PrintBTree_int(BT->right); //输出右子树
printf(")");
}
}
}
//2、根据数组 a 中 n 个权值建立一棵哈夫曼树,返回树根指针
struct BTreeNode* CreateHuffman(ElemType a[], int n)
{
int i, j;
struct BTreeNode **b, *q;
b = malloc(n*sizeof(struct BTreeNode));
for (i = 0; i < n; i++) //初始化b指针数组,使每个指针元素指向a数组中对应的元素结点
{
b[i] = malloc(sizeof(struct BTreeNode));
b[i]->data = a[i];
b[i]->left = b[i]->right = NULL;
}
for (i = 1; i < n; i++)//进行 n-1 次循环建立哈夫曼树
{
//k1表示森林中具有最小权值的树根结点的下标,k2为次最小的下标
int k1 = -1, k2;
for (j = 0; j < n; j++)//让k1初始指向森林中第一棵树,k2指向第二棵
{
if (b[j] != NULL && k1 == -1)
{
k1 = j;
continue;
}
if (b[j] != NULL)
{
k2 = j;
break;
}
}
for (j = k2; j < n; j++)//从当前森林中求出最小权值树和次最小
{
if (b[j] != NULL)
{
if (b[j]->data < b[k1]->data)
{
k2 = k1;
k1 = j;
}
else if (b[j]->data < b[k2]->data)
k2 = j;
}
}
//由最小权值树和次最小权值树建立一棵新树,q指向树根结点
q = malloc(sizeof(struct BTreeNode));
q->data = b[k1]->data + b[k2]->data;
q->left = b[k1];
q->right = b[k2];
b[k1] = q;//将指向新树的指针赋给b指针数组中k1位置
b[k2] = NULL;//k2位置为空
}
free(b); //删除动态建立的数组b
return q; //返回整个哈夫曼树的树根指针
}
//3、求哈夫曼树的带权路径长度
ElemType WeightPathLength(struct BTreeNode* FBT, int len)//len初始为0
{
if (FBT == NULL) //空树返回0
return 0;
else
{
if (FBT->left == NULL && FBT->right == NULL)//访问到叶子结点
return FBT->data * len;
else //访问到非叶子结点,进行递归调用,返回左右子树的带权路径长度之和,len递增
return WeightPathLength(FBT->left,len+1)+WeightPathLength(FBT->right,len+1);
}
}
//4、哈夫曼编码(可以根据哈夫曼树带权路径长度的算法基础上进行修改)
void HuffManCoding(struct BTreeNode* FBT, int len)//len初始值为0
{
static int a[10];//定义静态数组a,保存每个叶子的编码,数组长度至少是树深度减一
if (FBT != NULL)//访问到叶子结点时输出其保存在数组a中的0和1序列编码
{
if (FBT->left == NULL && FBT->right == NULL)
{
int i;
printf("结点权值为%d的编码:", FBT->data);
for (i = 0; i < len; i++)
printf("%d", a[i]);
printf("
");
}
else//访问到非叶子结点时分别向左右子树递归调用,并把分支上的0、1编码保存到数组a
{ //的对应元素中,向下深入一层时len值增1
a[len] = 0;
HuffManCoding(FBT->left, len + 1);
a[len] = 1;
HuffManCoding(FBT->right, len + 1);
}
}
}
//主函数
void main()
{
int n, i;
ElemType* a;
struct BTreeNode* fbt;
printf("从键盘输入待构造的哈夫曼树中带权叶子结点数n:");
while(1)
{
scanf("%d", &n);
if (n > 1)
break;
else
printf("重输n值:");
}
a = malloc(n*sizeof(ElemType));
printf("从键盘输入%d个整数作为权值:", n);
for (i = 0; i < n; i++)
scanf(" %d", &a[i]);
fbt = CreateHuffman(a, n);
printf("广义表形式的哈夫曼树:");
PrintBTree_int(fbt);
printf("
");
printf("哈夫曼树的带权路径长度:");
printf("%d
", WeightPathLength(fbt, 0));
printf("树中每个叶子结点的哈夫曼编码:
");
HuffManCoding(fbt, 0);
}
1
149
1
2
3
typedef int ElemType;
4
struct BTreeNode
5
{
6
ElemType data;
7
struct BTreeNode* left;
8
struct BTreeNode* right;
9
};
10
11
//1、输出二叉树,可在前序遍历的基础上修改。采用广义表格式,元素类型为int
12
void PrintBTree_int(struct BTreeNode* BT)
13
{
14
if (BT != NULL)
15
{
16
printf("%d", BT->data); //输出根结点的值
17
if (BT->left != NULL || BT->right != NULL)
18
{
19
printf("(");
20
PrintBTree_int(BT->left); //输出左子树
21
if (BT->right != NULL)
22
printf(",");
23
PrintBTree_int(BT->right); //输出右子树
24
printf(")");
25
}
26
}
27
}
28
29
//2、根据数组 a 中 n 个权值建立一棵哈夫曼树,返回树根指针
30
struct BTreeNode* CreateHuffman(ElemType a[], int n)
31
{
32
int i, j;
33
struct BTreeNode **b, *q;
34
b = malloc(n*sizeof(struct BTreeNode));
35
for (i = 0; i < n; i++) //初始化b指针数组,使每个指针元素指向a数组中对应的元素结点
36
{
37
b[i] = malloc(sizeof(struct BTreeNode));
38
b[i]->data = a[i];
39
b[i]->left = b[i]->right = NULL;
40
}
41
for (i = 1; i < n; i++)//进行 n-1 次循环建立哈夫曼树
42
{
43
//k1表示森林中具有最小权值的树根结点的下标,k2为次最小的下标
44
int k1 = -1, k2;
45
for (j = 0; j < n; j++)//让k1初始指向森林中第一棵树,k2指向第二棵
46
{
47
if (b[j] != NULL && k1 == -1)
48
{
49
k1 = j;
50
continue;
51
}
52
if (b[j] != NULL)
53
{
54
k2 = j;
55
break;
56
}
57
}
58
for (j = k2; j < n; j++)//从当前森林中求出最小权值树和次最小
59
{
60
if (b[j] != NULL)
61
{
62
if (b[j]->data < b[k1]->data)
63
{
64
k2 = k1;
65
k1 = j;
66
}
67
else if (b[j]->data < b[k2]->data)
68
k2 = j;
69
}
70
}
71
//由最小权值树和次最小权值树建立一棵新树,q指向树根结点
72
q = malloc(sizeof(struct BTreeNode));
73
q->data = b[k1]->data + b[k2]->data;
74
q->left = b[k1];
75
q->right = b[k2];
76
77
b[k1] = q;//将指向新树的指针赋给b指针数组中k1位置
78
b[k2] = NULL;//k2位置为空
79
}
80
free(b); //删除动态建立的数组b
81
return q; //返回整个哈夫曼树的树根指针
82
}
83
84
//3、求哈夫曼树的带权路径长度
85
ElemType WeightPathLength(struct BTreeNode* FBT, int len)//len初始为0
86
{
87
if (FBT == NULL) //空树返回0
88
return 0;
89
else
90
{
91
if (FBT->left == NULL && FBT->right == NULL)//访问到叶子结点
92
return FBT->data * len;
93
else //访问到非叶子结点,进行递归调用,返回左右子树的带权路径长度之和,len递增
94
return WeightPathLength(FBT->left,len+1)+WeightPathLength(FBT->right,len+1);
95
}
96
}
97
98
//4、哈夫曼编码(可以根据哈夫曼树带权路径长度的算法基础上进行修改)
99
void HuffManCoding(struct BTreeNode* FBT, int len)//len初始值为0
100
{
101
static int a[10];//定义静态数组a,保存每个叶子的编码,数组长度至少是树深度减一
102
if (FBT != NULL)//访问到叶子结点时输出其保存在数组a中的0和1序列编码
103
{
104
if (FBT->left == NULL && FBT->right == NULL)
105
{
106
int i;
107
printf("结点权值为%d的编码:", FBT->data);
108
for (i = 0; i < len; i++)
109
printf("%d", a[i]);
110
printf("
");
111
}
112
else//访问到非叶子结点时分别向左右子树递归调用,并把分支上的0、1编码保存到数组a
113
{ //的对应元素中,向下深入一层时len值增1
114
a[len] = 0;
115
HuffManCoding(FBT->left, len + 1);
116
a[len] = 1;
117
HuffManCoding(FBT->right, len + 1);
118
}
119
}
120
}
121
122
//主函数
123
void main()
124
{
125
int n, i;
126
ElemType* a;
127
struct BTreeNode* fbt;
128
printf("从键盘输入待构造的哈夫曼树中带权叶子结点数n:");
129
while(1)
130
{
131
scanf("%d", &n);
132
if (n > 1)
133
break;
134
else
135
printf("重输n值:");
136
}
137
a = malloc(n*sizeof(ElemType));
138
printf("从键盘输入%d个整数作为权值:", n);
139
for (i = 0; i < n; i++)
140
scanf(" %d", &a[i]);
141
fbt = CreateHuffman(a, n);
142
printf("广义表形式的哈夫曼树:");
143
PrintBTree_int(fbt);
144
printf("
");
145
printf("哈夫曼树的带权路径长度:");
146
printf("%d
", WeightPathLength(fbt, 0));
147
printf("树中每个叶子结点的哈夫曼编码:
");
148
HuffManCoding(fbt, 0);
149
}