数据结构---赫夫曼树
数据结构---二叉树递归遍历
数据结构---二叉树非递归遍历
#if 0
/**********************************************/
/************数据结构实验---赫夫曼树***********/
/**********************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
unsigned int weight; //节点权值
unsigned int parent, lchild, rchild; //节点的父指针,左//右孩子指针
}HTNode, *HuffmanTree;
typedef char **HuffmanCode; //赫夫曼编码表
void CreateHuffmanTree(HuffmanTree &HT, unsigned int *w/*叶子节点权值*/, const int n); //生成一棵赫夫曼树
void HuffmanCoding(HuffmanTree HT, HuffmanCode &HC, const int n); //对赫夫曼树进行编码
void PrintHuffmanCode(HuffmanCode HC, unsigned int *w, const int n); //打印赫夫曼编码
void Select(HuffmanTree HT, int t, int&s1, int&s2); //寻找权值最小的两个节点
int main()
{
HuffmanTree HT; //赫夫曼树HT
HuffmanCode HC; //赫夫曼编码表HC
int n, i; //n是赫夫曼树叶子节点数
unsigned int* w; //w存放叶子节点权值
char j = 'y';
//程序解说
printf("构造赫夫曼树:\n");
printf("输入叶子节点数目.\n例如:8\n");
printf("然后输入每个叶子节点的权值.\n");
printf("例如:5 29 7 8 14 23 3 11\n");
printf("构造一棵哈夫曼树并显示赫夫曼编码.\n");
while (j != 'N' && j != 'n')
{
printf("请输入叶子节点数目:");
scanf("%d", &n); //输入叶子节点数
if (n <= 1)
{
printf("该数不合理!\n");
continue;
}
w = (unsigned int*)malloc(n * sizeof(unsigned int)); //开辟空间存放权值
printf("请输入各叶子节点的权值:\n");
for (i = 0; i < n; i++)
scanf("%d", &w[i]);
CreateHuffmanTree(HT, w, n); //创建赫夫曼树
HuffmanCoding(HT, HC, n); //进行赫夫曼编码
PrintHuffmanCode(HC, w, n); //显示赫夫曼编码
printf("赫夫曼树构造完毕,还要继续吗?(Y/N)");
scanf(" %c", &j);
}
return 0;
}
void CreateHuffmanTree(HuffmanTree &HT, unsigned int *w/*叶子节点权值*/, const int n)
{
int i, m;
int s1, s2; //存放节点权值最小的两个叶子
HuffmanTree p;
if (n <= 1) return;
m = 2 * n - 1; //n个叶子节点的赫夫曼树,有2*n-1 //个节点
HT = (HuffmanTree)malloc((m + 1)*sizeof(HTNode)); //开辟2*n各节点空间,0号单元不用
for (p = HT + 1, i = 1; i <= n; ++i, ++p, ++w) //原来的节点进行初始化
{
p->weight = *w;
p->parent = 0;
p->lchild = 0;
p->rchild = 0;
}
for (; i <= m; ++i, ++p)//新开辟的节点进行初始化
{
p->weight = 0;
p->parent = 0;
p->lchild = 0;
p->rchild = 0;
}
for (i = n + 1; i <= m; ++i) //建赫夫曼树
{
Select(HT, i - 1, s1, s2);
//从HT[1...i-1]中选择parent为0且weight //最小的两个节点,其序号分别为s1和s2
HT[s1].parent = i; HT[s2].parent = i; //修改s1和//s2节点的父指针parent
HT[i].lchild = s1; HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight; //修改权值
}
}
void HuffmanCoding(HuffmanTree HT, HuffmanCode &HC, const int n)
{
int i, c, f, start;
char *cd; //将有n个叶子节点的赫夫曼树HT进行编码,码存放在HC中
//方法是从叶子到根逆向求每个叶子节点的赫夫曼编码
HC = (HuffmanCode)malloc((n + 1)*sizeof(char *));
cd = (char *)malloc(n*sizeof(char)); //开辟一个求编码的临时工作空间
cd[n - 1] = '\0'; //字符串结束符
for (i = 1; i <= n; ++i) //逐个地求赫夫曼编码
{
start = n - 1; //编码结束位置
for (c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent) //从叶子到根逆向求编码
if (HT[f].lchild == c) cd[--start] = '0'; //若是左孩子编为'0'
else cd[--start] = '1'; //若是右孩子编为'1'
HC[i] = (char *)malloc((n - start)*sizeof(char)); //为第i个编码分配空间
strcpy(HC[i], &cd[start]); //将编码从cd复制到HC中
}
free(cd); //释放工作空间
}
void PrintHuffmanCode(HuffmanCode HC, unsigned int *w, int n)
{//显示有n个叶子节点的赫夫曼树的编码表
int i;
printf("HuffmanCode is :\n");
for (i = 1; i <= n; i++)
{
printf(" %3d---", w[i - 1]);
puts(HC[i]);
}
printf("\n");
}
void Select(HuffmanTree HT, int t, int&s1, int&s2)
{//在HT[1...t]中选择parent不为0且权值最小的两//个节点,其序号分别为s1和s2
int i, m, n;
m = n = 10000;
for (i = 1; i <= t; i++)
{
if ((HT[i].parent == 0) && ((HT[i].weight<m) || (HT[i].weight<n)))
if (m<n)
{
n = HT[i].weight; s2 = i;
}
else { m = HT[i].weight; s1 = i; }
}
if (s1>s2) //s1放较小的序号
{
i = s1; s1 = s2; s2 = i;
}
}
#elif 0
/****************************************/
/**********数据结构---二叉树递归遍历*****/
/****************************************/
#include<iostream>
using namespace std;
typedef struct node//定义节点
{
struct node *lchild;
struct node *rchild;
char data;
}BiTreeNode, *BiTree;
//按照先序顺序建立二叉树
void createPreBiTree(BiTree &T)
{
char c;
cin >> c;
if ('#' == c) //当遇到#时,令树的根节点为NULL
T = NULL;
else
{
T = new BiTreeNode;
T->data = c;
createPreBiTree(T->lchild);
createPreBiTree(T->rchild);
}
}
//按照中序建立二叉树
void createMinBiTree(BiTree &T)
{
char c;
cin >> c;
if ('#' == c)
T = NULL;
else
{
T = new BiTreeNode;
createMinBiTree(T->lchild);
T->data = c;
createMinBiTree(T->rchild);
}
}
//按照后序建立二叉树
void createPostBiTree(BiTree &T)
{
char c;
cin >> c;
if ('#' == c)
T = NULL;
else
{
T = new BiTreeNode;
createPostBiTree(T->lchild);
createPostBiTree(T->rchild);
T->data = c;
}
}
//前序遍历二叉树并打印
void preTraverse(BiTree T)
{
if (T)
{
cout << T->data << " ";
preTraverse(T->lchild);
preTraverse(T->rchild);
}
}
//中序遍历二叉树并打印
void midTraverse(BiTree T)
{
if (T)
{
midTraverse(T->lchild);
cout << T->data << " ";
midTraverse(T->rchild);
}
}
//后续遍历二叉树并打印
void postTraverse(BiTree T)
{
if (T)
{
postTraverse(T->lchild);
postTraverse(T->rchild);
cout << T->data << " ";
}
}
int main()
{
BiTree T;
createPreBiTree(T);
cout << "二叉树创建完成!" << endl;
cout << "先序遍历二叉树:" << endl;
preTraverse(T);
cout << endl;
cout << "中序遍历二叉树:" << endl;
midTraverse(T);
cout << endl;
cout << "后序遍历二叉树:" << endl;
postTraverse(T);
return 0;
}
#elif 1
/******************************************************/
/***********数据结构实验---二叉树非递归遍历************/
/******************************************************/
#include <iostream>
#include<string.h>
#include<stack> //STL模板库栈
using std::stack;//模板栈定义在std命名空间里
using std::cout;
using std::endl;
typedef struct node //二叉树节点
{
char data;
struct node *lchild, *rchild;
}BinTree;
typedef struct node1
{
BinTree *btnode;
bool isFirst;
}BTNode;
void creatBinTree(char *s, BinTree *&root) //创建二叉树,s为形如A(B,C(D,E))形式的字符串
{
int i;
bool isRight = false;
stack<BinTree*> s1; //存放结点
stack<char> s2; //存放分隔符
BinTree *p, *temp;
root->data = s[0];
root->lchild = nullptr;
root->rchild = nullptr;
s1.push(root);
i = 1;
while (i<strlen(s))
{
if (s[i] == '(')
{
s2.push(s[i]);
isRight = false;
}
else if (s[i] == ',')
{
isRight = true;
}
else if (s[i] == ')')
{
s1.pop();
s2.pop();
}
else if (isalpha(s[i]))
{
p = (BinTree *)malloc(sizeof(BinTree));
p->data = s[i];
p->lchild = nullptr;
p->rchild = nullptr;
temp = s1.top();
if (isRight == true)
{
temp->rchild = p;
cout << temp->data << "的右孩子是" << s[i] << endl;
}
else
{
temp->lchild = p;
cout << temp->data << "的左孩子是" << s[i] << endl;
}
if (s[i + 1] == '(')
s1.push(p);
}
i++;
}
}
void display(BinTree *root) //显示树形结构
{
if (root != nullptr)
{
cout << root->data;
if (root->lchild != nullptr)
{
cout << '(';
display(root->lchild);
}
if (root->rchild != nullptr)
{
cout << ',';
display(root->rchild);
cout << ')';
}
}
}
void preOrder1(BinTree *root) //递归前序遍历
{
if (root != nullptr)
{
cout << root->data << " ";
preOrder1(root->lchild);
preOrder1(root->rchild);
}
}
void inOrder1(BinTree *root) //递归中序遍历
{
if (root != nullptr)
{
inOrder1(root->lchild);
cout << root->data << " ";
inOrder1(root->rchild);
}
}
void postOrder1(BinTree *root) //递归后序遍历
{
if (root != nullptr)
{
postOrder1(root->lchild);
postOrder1(root->rchild);
cout << root->data << " ";
}
}
void preOrder2(BinTree *root) //非递归前序遍历
{
stack<BinTree*> s;
BinTree *p = root;
while (p != nullptr || !s.empty())
{
while (p != nullptr)
{
cout << p->data << " ";
s.push(p);
p = p->lchild;
}
if (!s.empty())
{
p = s.top();
s.pop();
p = p->rchild;
}
}
}
void inOrder2(BinTree *root) //非递归中序遍历
{
stack<BinTree*> s;
BinTree *p = root;
while (p != nullptr || !s.empty())
{
while (p != nullptr)
{
s.push(p);
p = p->lchild;
}
if (!s.empty())
{
p = s.top();
cout << p->data << " ";
s.pop();
p = p->rchild;
}
}
}
void postOrder2(BinTree *root) //非递归后序遍历
{
stack<BTNode*> s;
BinTree *p = root;
BTNode *temp;
while (p != nullptr || !s.empty())
{
while (p != nullptr) //沿左子树一直往下搜索,直至出现没有左子树的结点
{
BTNode *btn = (BTNode *)malloc(sizeof(BTNode));
btn->btnode = p;
btn->isFirst = true;
s.push(btn);
p = p->lchild;
}
if (!s.empty())
{
temp = s.top();
s.pop();
if (temp->isFirst == true) //表示是第一次出现在栈顶
{
temp->isFirst = false;
s.push(temp);
p = temp->btnode->rchild;
}
else //第二次出现在栈顶
{
cout << temp->btnode->data << " ";
p = nullptr;
}
}
}
}
void postOrder3(BinTree *root) //非递归后序遍历
{
stack<BinTree*> s;
BinTree *cur; //当前结点
BinTree *pre = nullptr; //前一次访问的结点
s.push(root);
while (!s.empty())
{
cur = s.top();
if ((cur->lchild == nullptr&&cur->rchild == nullptr) ||
(pre != nullptr && (pre == cur->lchild || pre == cur->rchild)))
{
cout << cur->data << " "; //如果当前结点没有孩子结点或者孩子节点都已被访问过
s.pop();
pre = cur;
}
else
{
if (cur->rchild != nullptr)
s.push(cur->rchild);
if (cur->lchild != nullptr)
s.push(cur->lchild);
}
}
}
int main(int argc, char *argv[])
{
char s[100];
while (scanf("%s", s) == 1)
{
BinTree *root = (BinTree *)malloc(sizeof(BinTree));
creatBinTree(s, root);
display(root);
cout << endl;
preOrder2(root);
cout << endl;
inOrder2(root);
cout << endl;
postOrder2(root);
cout << endl;
postOrder3(root);
cout << endl;
}
return 0;
}
#endif