
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 struct11
{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 CTNode42
{43
int child;44
struct CTNode *next;45
}*ChildPtr;46
47
typedef struct48
{49
TElemType data;50
int parent;51
ChildPtr firstChild;52
}CTBox;53
54
typedef struct55
{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 Tree11
{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_H27
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
else44
{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
else79
{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
}