///本想着复习一下 二叉树就学哈夫曼的 呵呵哒 复习就用了一晚上 这效率也是没谁了
///都粘上。。。
/*
#include<iostream>
#include<queue>
using namespace std;
const int maxn = 100;
int n = 0, m = 0;
typedef struct treenode
{
char data;
treenode *lchild;
treenode *rchild;
}node, *Tree;
int num = 0;
node *q[100];
int head = 0;
int tail = 0;
node *createtree(node *t)
{
char a;
cin >> a;
if(a == '0')
return NULL;
t = new node;
t->data = a;
t->lchild = createtree(t->lchild);
t->rchild = createtree(t->rchild);
return t;
}
void in_order(node *t)
{
if(t)
{
in_order(t->lchild);
cout << t->data;
in_order(t->rchild);
}
}
bool is_Empty()
{
int flag = 0;
for(int i=head; i<tail; i++)///最开始这里写的1~maxn 层序遍历之后就会崩掉
{ ///因为那些出队的元素 实际上还存在在数组里 出队就是不在头和尾之间
if(q[i] != NULL)
{
flag = 1;
break;
}
}
if(flag)
return false;
return true;
}
void level_order(node *t)
{*/
/*if(t)
{
queue<node*>q;
while(!q.empty())
q.pop();
q.push(t);
while(!q.empty())
{
node *a = q.front();
q.pop();
cout << a->data;
if(a->lchild)
q.push(a->lchild);
if(a->rchild)
q.push(a->rchild);
}
}*/
///用STL习惯了 都不会数组的了
///数组模拟队列 是 只输出head 和tail之间的~
/* if(t)///head 控制出队 tail控制入队 先进先出~
{
while(!is_Empty())
{
tail--;
}
q[tail++] = t;///根节点入队
while(!is_Empty())
{
node *a = q[head];///取出队首元素
head++;///出队
cout << a->data;
if(a->lchild)
q[tail++] = a->lchild;
if(a->rchild)
q[tail++] = a->rchild;
}
}
}
int dep(node *t)
{
int depth;
if(t)
{
if(t->lchild)
{
dep(t->lchild);
m++;
}
if(t->rchild)
{
dep(t->rchild);
n++;
}
}
depth = m>n?m:n;
return depth;
}
int leaves(node *t)
{
if(t)
{
if(t->lchild)
leaves(t->lchild);
if(t->lchild == NULL && t->rchild == NULL)
{
num++;
}
if(t->rchild)
leaves(t->rchild);
}
return num; ///这样写的结果就是输出122333 可以做个数组然后输出最后一个 但是这也太麻烦了 所以还是看正常解法吧
}///哈哈哈 果然做个返回值最直接啊 哈哈哈哈哈哈哈哈哈哈哈
bool is_Empty(node *t)
{
if(t)///
return false;
return true;
}
node *point(node *t, char e)///在树里找值为e的节点
{
///这里就要BFS了 为了考试不挂 那就数组模拟队列吧 T^T
if(t)
{
head = 0;
tail = 0;///头尾相等就是空
q[tail++] = t;
while(head!=tail)
{
node *a = q[head];
head++;
if(a->data == e)
return a;
if(a->lchild)
q[tail++] = a->lchild;
if(a->rchild)
q[tail++] = a->rchild;
}
}
return NULL;
}
node *parent(node *t, char e)
{
node *p = point(t, e);///找到e这个节点了 那么接着就是找p的双亲了
head = 0;
tail = 0;
q[tail++] = t;
while(head!=tail)
{
node *a = q[head];
head++;
if(a->lchild == p || a->rchild==p)
return a;
if(a->lchild)
q[tail++] = a->lchild;
if(a->rchild)
q[tail++] = a->rchild;
}
return NULL;
}
void insert_node(node *t, node *t1, char e1, int LR)///e1是要找的节点的值
{///LR是插在哪里
if(t)
{
node *p = point(t, e1);///
if(p == NULL)
{
cout << "not founded" << endl;
return;
}
node *tmp = p;
if(LR == 0)
{
while(tmp->lchild)
{
tmp = tmp->lchild;
}
tmp->lchild = t1;
}
else if(LR == 1)
{
while(tmp->rchild)
{
tmp = tmp->rchild;
}
tmp->rchild = t1;
}
}
///node *q = parent(t, e1);
}
void delete_node(node *t1, char e, int LR)
{
if(t1)
{
node *p = point(t1, e);
if(p == NULL)
{
cout << "not founded" << endl;
return;
}
if(LR == 0)
{
p->lchild = NULL;
}
else if(LR == 1)
{
p->rchild = NULL;
}
}
}*/
/*
node* destroy(node *t)///node 不让引用 *Tree才让引用 但是我弄返回值 把删掉的根节点返回去 应该没有问题呀
{
if(t){
if(t->lchild)
destroy(t->lchild);
if(t->rchild)
destroy(t->rchild);
delete t;
t = NULL;
return t;
}
}
*/
/*
void destroy(Tree &t)///node 不让引用 *Tree才让引用 但是我弄返回值 把删掉的根节点返回去 应该没有问题呀
{
if(t){
if(t->lchild)
destroy(t->lchild);
if(t->rchild)
destroy(t->rchild);
delete t;
t = NULL;
}
}*/
///下面的销毁错错错 我按左根右的顺序去删除 但是但是但是 根都被删除了 我还怎么去找右啊 所以错错错
/*
void destroy(node *t)
{
if(t)
{
if(t->lchild)
destroy(t->lchild);
cout << "1" << endl;
/// t = NULL;
delete t;
if(t->rchild)
destroy(t->rchild);
}
}*/
/*
int main()
{
///int a[100] = {8, 2 , 7, 89, 3, 62, 23, 15, 4, 10};
node *tree, *t1;
tree = new node;
tree->lchild = NULL;
tree->rchild = NULL;
t1 = new node;
t1->lchild = NULL;
t1->rchild = NULL;
tree = createtree(tree);
cout << "in_order" << endl;
in_order(tree);
cout << endl;
t1 = createtree(t1);
cout << "level_order" << endl;
level_order(t1);
cout << endl;
cout << "the depth is" << endl;
int depth = dep(t1);
cout << depth << endl;
cout << "the leaves are" << endl;
int num = leaves(t1);
cout << num;
cout << endl;
cout << "find e" << endl;
node *p = point(t1,'d');
cout << "find parent" << endl;
node *q = parent(t1, 'a');
if(q)
cout << q->data << endl;
else
cout << "NULL" << endl;
if(p)
cout << p->data << endl;
else
cout << "not founded" << endl;
cout << "insert node:" << endl;
insert_node(t1, tree, 'c', 1);
cout << "after insert(level_order):" << endl;
level_order(t1);
cout << "delete node:" << endl;
delete_node(t1, 'a', 0);
level_order(t1);
cout << endl;
destroy(t1);
if(t1)
cout << "No" << endl;///这里留下 做个对比吧 我以为会输出Yes呢 结果却是No
else
cout << "Yes" << endl;
if(is_Empty(t1))
cout << "YES" << endl;///这里是YES 呵呵哒 忘传参了 这里也是NO 我的销毁操作根本没起作用 呵呵呵呵哒
else
cout << "NO" << endl;
return 0;
}
*/
/*
abe00f00cd000
*/
/*
#include<iostream>
#include<queue>
using namespace std;
typedef struct treenode
{
int data;
treenode *lchild;
treenode *rchild;
}node, *Tree;
node *q[100];
int head, tail;
int flag = 0;
int arr[15] = {4, 17, 2, 67, 15, 7, 13, 9, 19, 10};
void insert_node(node *t, node *child)
{
if(t)
{
if(t->lchild && t->data >= child->data)
{
insert_node(t->lchild, child);
}
if(t->rchild && t->data < child->data)
{
insert_node(t->rchild, child);
}
if(t->lchild == NULL && child->data <= t->data)
{
t->lchild = child;
}
else if(t->rchild == NULL && child->data > t->data)
t->rchild = child;
}
}
void create_node(Tree &t)///建树啊 删树啊 都得用引用 建树返回值也行 删树我没返回明白呢
{
node *child;
t = new node;
t->data = arr[0];
t->rchild = NULL;
t->lchild = NULL;
for(int i=1; i<10; i++)
{
child = new node;
child->lchild = NULL;
child->rchild = NULL;
child->data = arr[i];
insert_node(t, child);
}
}
void in_order(node *t)
{
if(t)
{
if(t->lchild)
in_order(t->lchild);
cout << t->data << ' ';
if(t->rchild)
in_order(t->rchild);
}
}
void level_order(node *t)
{
if(t)
{
head = 0;
tail = 0;
q[tail++] = t;
while(head!=tail)
{
node *a = q[head];
head++;
cout << a->data << ' ';
if(a->lchild)
q[tail++] = a->lchild;
if(a->rchild)
q[tail++] = a->rchild;
}
}
}
node *point(node *t, int e)
{
if(t)
{
head = 0;
tail = 0;
q[tail++] = t;
while(head!=tail)
{
node *a = q[head];
head++;
if(a->data == e)
return a;
if(a->lchild)
q[tail++] = a->lchild;
if(a->rchild)
q[tail++] = a->rchild;
}
}
return NULL;
}
node *parent(node *t, node *p)
{
if(t)
{
head = 0;
tail = 0;
q[tail++] = t;
while(head!=tail)
{
node *a = q[head];
head++;
if(a && a->lchild == p)
{
flag = 0;
return a;
}
if(a && a->rchild == p)
{
flag = 1;
return a;
}
if(a->lchild)
q[tail++] = a->lchild;
if(a->rchild)
q[tail++] = a->rchild;
}
}
return NULL;
}
void delete_node(Tree &t, int e)
{
if(t)
{
node *p = point(t, e);
if(p == NULL)///1.空
{
cout << "not founded" << endl;
return;
}
node *q = parent(t, p);
///2.有父节点 没有左右孩子
if(q && p->lchild == NULL && p->rchild == NULL)
{
if(flag == 0)
{
q->lchild = NULL;
delete p;
}
else if(flag == 1)
{
q->rchild = NULL;
delete p;
}
}
///3.有父节点 有左孩子 没右孩子
else if(q && p->lchild && p->rchild==NULL)
{
if(flag == 0)
{
q->lchild = p->lchild;
delete p;
}
else if(flag == 1)
{
q->rchild = p->lchild;
delete p;
}
}
///4.有父节点 没左孩子 有右孩子
else if(q && p->lchild == NULL && p->rchild)
{
if(flag == 0)
{
q->lchild = p->rchild;
delete p;
}
else if(flag == 1)
{
q->rchild = p->rchild;
delete p;
}
}
///5.有父节点 有左右孩子 假定左孩子放到原来的右节点上 右节点放左孩子上
else if(q && p->lchild && p->rchild)///那左孩子的左右节点怎么办呢 不能丢 就找地儿随便放得了
{
if(flag == 0)
{
q->lchild = p->lchild;
if(p->lchild->lchild && p->lchild->rchild)
{
node *tmp = p->lchild->lchild;
while(!tmp)
{
tmp = tmp->lchild;
}
tmp->lchild = p->lchild->rchild;
}
else if(p->lchild->lchild == NULL && p->lchild->rchild)
p->lchild->lchild = p->lchild->rchild;
else if(p->lchild->rchild == NULL && p->lchild->lchild)
p->lchild->rchild = p->lchild->lchild;
q->lchild->rchild = p->rchild;
delete p;
}
else if(flag == 1)
{
q->rchild = p->lchild;
if(p->lchild->lchild != NULL && p->lchild->rchild)
{
node *tmp = p->lchild->lchild;
while(!tmp)
{
tmp = tmp->lchild;
}
tmp->lchild = p->lchild->rchild;
}
else if(p->lchild->lchild == NULL && p->lchild->rchild)
p->lchild->lchild = p->lchild->rchild;
else if(p->lchild->rchild == NULL && p->lchild->lchild)
p->lchild->rchild = p->lchild->lchild;
q->rchild->rchild = p->rchild;
delete p;
}
}
///6.没父节点 没左右孩子
else if(q==NULL && p->rchild == NULL && p->lchild == NULL)
{
t = NULL;///第一次忘写了 我们并没有销毁树
delete p;
}
///7.没父节点 有左孩子 没右孩子
else if(q==NULL && p->lchild && p->rchild == NULL)
{
t = p->lchild;
delete p;
}
///8.没父节点 没左孩子 有右孩子
else if(q==NULL && p->rchild && p->lchild == NULL)
{
t = p->rchild;
delete p;
}
///9.没父节点 有左右孩子 假定左孩子上位
else if(q==NULL && p->lchild && p->rchild)
{///
/*t->rchild = p->rchild;*/ /// 真搞笑 这相当于没操作啊
/* node *tmp;
tmp = p;
t = p->lchild;
t->rchild = p->rchild;
delete p;
}
}
}
bool is_Empty(node *t)
{
if(t)
return false;
return true;
}
void destroy(Tree &t)
{
if(t)
{
destroy(t->lchild);
destroy(t->rchild);
t = NULL;
delete t;
}
}
int main()
{
node *t1, *t2;
create_node(t1);
cout << "in_order:" << endl;
in_order(t1);
cout << endl;
cout << "level_order :" << endl;
level_order(t1);
cout << endl;
cout << "insert a node:" << endl;
int n;
cin >> n;
node *p;
p = new node;
p->lchild = NULL;///
p->rchild = NULL;
p->data = n;
insert_node(t1, p);
cout << "level_order: " << endl;
level_order(t1);///后面什么都不写的话 那黑框框直接就消失了 我好方啊
cout << endl;
cout << "delete node :" << endl;
int s;
while(1)
{
cin >> s;
delete_node(t1, s);
cout << "level order is" << endl;
level_order(t1);
cout << endl;
if(t1 == NULL)
cout << "NULL" << endl;
}
destroy(t1);
if(is_Empty(t1))
{
cout << "empty!" << endl;
}
if(t1 == NULL)
cout << "NULL" << endl;
cin >> s;
return 0;
}*/
///这次写又遇到了不少问题 又用了一晚上 本来以为很快就能写完的 可是老遇到BUG 不过我很享受这个过程
///用着瑞瑞的电脑 瑞瑞的机械键盘 感觉好爽啊 哈哈哈哈
/*
in_order:
2 4 7 9 10 13 15 17 19 67
level_order :
4 2 17 15 67 7 19 13 9 10
insert a node:
1
level_order:
4 2 17 1 15 67 7 19 13 9 10
delete node :
2
level order is
4 1 17 15 67 7 19 13 9 10
15
level order is
4 1 17 7 67 13 19 9 10
17
level order is
4 1 7 13 67 9 19 10
67
level order is
4 1 7 13 19 9 10
4
level order is
1 7 13 19 9 10
13
level order is
1 7 9 19 10
19
level order is
1 7 9 10
7
level order is
1 9 10
9
level order is
1 10
10
level order is
1
1
level order is
NULL
*/
///这个挺好玩 要多大就分配多大 不浪费空间
///伪代码
/*
int main()
{
int n;
int *a;
while(1)
{
scanf("%d", &n);
if(n>1)
break;
else
printf("请重新输入\n");
}
a = malloc(sizeof(n*int));
}*/
#include<iostream>
using namespace std;
typedef struct treenode
{
int data;
treenode *lchild;
treenode *rchild;
}node, *Tree;
int a[100];
void print(node *t)///先序遍历
{
if(t)
{
cout << t->data;
if(t->lchild || t->rchild)
{
cout << "(" ;
if(t->lchild)
print(t->lchild);
if(t->rchild)
{
cout << ",";
print(t->rchild);
}
cout << ")";
}
}
}
node *createHuffmantree(int n)
{
node *b[100], *q;
for(int i=0; i<n; i++)///初始化b指针数组,使每个指针元素指向a数组中对应的元素结点
{
b[i] = new node;
b[i]->data = a[i];
b[i]->lchild = b[i]->rchild = NULL;
}
for(int i=0; i<n-1; i++)///循环n-1次 建立哈夫曼树
{
///k1表示森林中具有最小权值的树根结点的下标,k2为次最小的下标
int k1 = -1, k2;
for(int j=0; j<n; j++)///让k1初始指向森林中第一棵树,k2指向第二棵
{
if(k1 == -1 && b[j])
{
k1 = j;
cout << k1 << endl;
continue;
}
if(b[j])
{
k2 = j;
cout << k2 << endl;
break;
}///我觉得k1 永远是0, k2 永远是1 呵呵哒 你错了
}
for(int j=k2; j<n; j++)
{
if(b[j])///第一次 比较b[k2]->data 与b[k1]->data 小的为k1。。。
{
if(b[j]->data < b[k1]->data)
{
k2 = k1;///因为本来k1是最小的 现在找到比k1小的了 那次小的就是k1
k1 = j;
}
else if(b[j]->data < b[k2]->data)
{
k2 = j;
}
}
}///最小的和次小的节点寻找完毕 可惜我道行尚浅 竟然没看出这是什么排序 T^T 又要复习排序了
q = new node;///计算新节点
q->data = b[k1]->data + b[k2]->data;
q->lchild = b[k1];
q->rchild = b[k2];
b[k1] = q;///那就是下一步要形成的树左子树为q, 右子树为空
b[k2] = NULL;///次优的置空
///那接下来 森林就是最优 次优结合体 与 其他的小叶子 重复以上步骤 ~~~
///分析完毕 抽抽抽抽风风风风
}
delete []b;
return q;
}
int weight_path_length(node *t, int len)
{
if(t)
{
if(t->lchild == NULL && t->rchild == NULL)
{
return t->data * len;
}
else
{
return weight_path_length(t->lchild, len+1)+weight_path_length(t->rchild, len+1);
}
}
return 0;
}
void HuffmanCode(node *t, int len)///后序遍历的顺序
{
static int a[10];
if(t)
{
if(t->lchild == NULL && t->rchild == NULL)
{
for(int i=0; i<len; i++)
cout << a[i];
cout << endl;
}
else
{
a[len] = 0;
HuffmanCode(t->lchild, len+1);
a[len] = 1;
HuffmanCode(t->rchild, len+1);
}
}
}
int main()
{
int n;
cin >> n;
for(int i=0; i<n; i++)
cin >> a[i];
node *tree = createHuffmantree(n);
cout << "广义表形式的哈夫曼树:" << endl;
print(tree);
cout << endl;
cout << "哈夫曼树的带权路径长度:" << endl;
cout << weight_path_length(tree, 0) << endl;
cout << "每个叶子节点的哈夫曼编码:" << endl;
HuffmanCode(tree, 0);
cout << endl;
for(int i=0; i<n; i++)
cout << a[i];/// 4 2 1 3
return 0;
}
/*
4
4 2 1 3
0
1
0
2
0
2
广义表形式的哈夫曼树:
10(4,6(3(1,2),3))
哈夫曼树的带权路径长度:
19
每个叶子节点的哈夫曼编码:
0
100
101
11
Process returned 0 (0x0) execution time : 10.987 s
Press any key to continue.
*/
哈夫曼树
最新推荐文章于 2021-09-03 10:57:42 发布