二叉树的基本操作

一、 实验目的
1.掌握二叉树的存储实现。
2.掌握二叉树的遍历思想。
3.掌握二叉树的常见算法的程序实现。
4. 掌握哈夫曼树和哈夫曼编码的基本思想和算法的程序实现。

二、 实验内容及要求
(1) 从键盘上输入数据,建立二叉链表。
(2) 前序遍历、中序遍历、后序遍历二叉树:递归算法。
(3) 哈夫曼树的构造与编码*;

(a)修理牧场:农夫要修理牧场的一段栅栏,他测量了栅栏,发现需要N块木头,每块木头长度为整数Li个长度单位,于是他购买了一条很长的、能锯成N块的木头,即该木头的长度是Li的总和。
但是农夫自己没有锯子,请人锯木头的酬金跟这段木头的长度成正比。为简单起见,不妨就设酬金等于所锯木头的长度。例如,要将长度为20的木头锯成长度为8、7和5的三段,第一次锯木头花费20,将木头锯成12和8;第二次锯木头花费12,将长度为12的木头锯成7和5,总花费为32。如果第一次将木头锯成15和5,则第二次锯木头花费15,总花费为35(大于32)。
请编写程序帮助农夫计算将木头锯成N块的最少花费。
首先输入一个正整数N(N≤104),表示要将木头锯成N块。接着给出N个正整数Li(Li≤50),表示每段木块的长度。输出一个整数,即将木头锯成N块的最少花费。
例如:
输入:
8
4 5 1 2 1 3 1 1
输出:
49
*(b)压缩软件:
给定一篇文章,只含有英文大小写字母和空格,以.txt格式存储,统计该文件中各种字符的频率,对各字符进行Huffman编码,将该文件翻译成Huffman编码文件,再将Huffman编码文件翻译成源文件。

Function.h

#include <stdio.h>
#include <stdlib.h>
typedef char BiElemType;
typedef struct BiTNode{
    BiElemType c;
    struct BiTNode *lchild;
    struct BiTNode *rchild;
}BiTNode,*BiTree;

typedef struct tag{
    BiTree p;    struct tag *pnext;
}tag_t,*ptag_t;

#define MaxSize 50
typedef BiTree ElemType;
typedef struct{
    ElemType data[MaxSize];
    int top;
}SqStack;
void InitStack(SqStack &S);
bool StackEmpty(SqStack &S);
bool Push(SqStack &S,ElemType x);
bool Pop(SqStack &S,ElemType &x);
bool GetTop(SqStack &S,ElemType &x);
typedef struct LinkNode{
    ElemType data;
    struct LinkNode *next;
}LinkNode;
typedef struct{
    LinkNode *front,*rear;
}LinkQueue;
void InitQueue(LinkQueue &Q);
bool IsEmpty(LinkQueue Q);
void EnQueue(LinkQueue &Q,ElemType x);
bool DeQueue(LinkQueue &Q,ElemType &x);

Queue.cpp

#include "function.h"
void InitQueue(LinkQueue &Q)
{
    Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));
    Q.front->next=NULL;
}

bool IsEmpty(LinkQueue Q)
{
    if(Q.front==Q.rear)
        return true;
    else
        return false;
}

void EnQueue(LinkQueue &Q,ElemType x)
{
    LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
    s->data=x;s->next=NULL;
    Q.rear->next=s;
    Q.rear=s;
}

bool DeQueue(LinkQueue &Q,ElemType &x)
{
    if(Q.front==Q.rear) return false;
    LinkNode *p=Q.front->next;
    x=p->data;
    Q.front->next=p->next;
    if(Q.rear==p)
        Q.rear=Q.front;
    free(p);
    return true;
}

Stack.cpp

#include "function.h"


void InitStack(SqStack &S)
{
    S.top=-1;
}

bool StackEmpty(SqStack &S)
{
    if(S.top==-1)
        return true;
    else
        return false;
}
bool Push(SqStack &S,ElemType x)
{
    if(S.top==MaxSize-1)
    {
        return false;
    }
    S.data[++S.top]=x;
    return true;
}
bool Pop(SqStack &S,ElemType &x)
{
    if(-1==S.top)
        return false;
    x=S.data[S.top--];
    return true;
}
bool GetTop(SqStack &S,ElemType &x)
{
    if(-1==S.top)
        return false;
    x=S.data[S.top];
    return true;
}

Main.cpp

#include "function.h"

//abdhiejcfg
void preOrder(BiTree p)
{
    if(p!=NULL)
    {
        putchar(p->c);
        preOrder(p->lchild);
        preOrder(p->rchild);
    }
}
void InOrder(BiTree p)
{
    if(p!=NULL)
    {
        InOrder(p->lchild);
        putchar(p->c);
        InOrder(p->rchild);
    }
}
void PostOrder(BiTree p)
{
    if(p!=NULL)
    {
        PostOrder(p->lchild);
        PostOrder(p->rchild);
        putchar(p->c);
    }
}

void LevelOrder(BiTree T)
{
    LinkQueue Q;
    InitQueue(Q);
    BiTree p;
    EnQueue(Q,T);
    while(!IsEmpty(Q))
    {
        DeQueue(Q,p);
        putchar(p->c);
        if(p->lchild!=NULL)
            EnQueue(Q,p->lchild);
        if(p->rchild!=NULL)
            EnQueue(Q,p->rchild);
    }
}

int main()
{
    BiTree pnew;
    char c;
    BiTree tree=NULL;
    ptag_t phead=NULL,ptail=NULL,listpnew=NULL,pcur=NULL;
    //abcdefghij
    while(scanf("%c",&c)!=EOF)
    {
        if(c=='\n')
        {
            break;
        }
        pnew=(BiTree)calloc(1,sizeof(BiTNode));
        pnew->c=c;
        listpnew=(ptag_t)calloc(1,sizeof(tag_t));
        listpnew->p=pnew;
        if(NULL==tree)
        {
            tree=pnew;
            phead=listpnew;
            ptail=listpnew;
            pcur=listpnew;
            continue;
        }else{
            ptail->pnext=listpnew;
            ptail=listpnew;
        }
        if(NULL==pcur->p->lchild)
        {
            pcur->p->lchild=pnew;
        }else if(NULL==pcur->p->rchild)
        {
            pcur->p->rchild=pnew;
            pcur=pcur->pnext;
        }
    }
    printf("--------前序遍历----------\n");
    preOrder(tree);
    printf("\n--------中序遍历------------\n");
    InOrder(tree);
    printf("\n--------后序遍历------------\n");
    PostOrder(tree);
    printf("\n--------层次遍历-----------\n");
    LevelOrder(tree);
    printf("\n");
    system("pause");
} 

Huffman.cpp

//
// Created by AdministratorYWJ on 2022/4/26.
//
#include <cstdio>
#include <cstdlib>
#include <cstring>
typedef struct {
    int weight;                  //权值
    int parent, lchild, rchild;  //有无父节点,左孩子,右孩子
} HTNode, *HuffmanTree;            //动态分配数组存储哈夫曼树
typedef char **HuffmanCode;      //动态分配数组存储哈夫曼编码表
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n);   //构建哈夫曼树,求出哈夫曼编码
void Select(HuffmanTree HT, int n, int &s1, int &s2);                  //选择两个权值最小的节点
void outputfile(HuffmanCode HC, int n, char *a);                        //字符输出
void inputfile(char *str);                                            //字符读入
void Huffmans(int w[], char *str, int &n, char *a);                      //统计文件中各字符的个数
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *o, int n) {
    char *cd;
    int m, c, f, k = 0, start, i, s1, s2;
    int w[60];
    for (i = 0; i < 60; i++) {
        w[i] = 0;
    }
    for (i = 0; i < 60; i++) {
        if (o[i] != 0) {
            w[k] = o[i];
            k++;
        }
    }
    if (n < -1) return;
    m = 2 * n - 1;
    HT = (HuffmanTree) malloc((m + 1) * sizeof(HTNode));
    for (i = 1; i <= n; ++i) {
        HT[i].weight = w[i - 1];
        HT[i].parent = 0;
        HT[i].lchild = 0;
        HT[i].rchild = 0;
    }
    for (; i <= m; ++i) {
        HT[i].weight = 0;
        HT[i].parent = 0;
        HT[i].lchild = 0;
        HT[i].rchild = 0;
    }
    for (i = n + 1; i <= m; ++i) {
        Select(HT, i - 1, s1, s2);
        HT[s1].parent = i;
        HT[s2].parent = i;
        HT[i].lchild = s1;
        HT[i].rchild = s2;
        HT[i].weight = HT[s1].weight + HT[s2].weight;
    }
    printf("\n");

    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';
            else
                cd[--start] = '1';
        }
        HC[i] = (char *) malloc((n - start) * sizeof(char));
        strcpy(HC[i], &cd[start]);
    }
    free(cd);
}

//选择两个权值最小的节点
void Select(HuffmanTree HT, int n, int &s1, int &s2) {
    int i, w;
    s1 = s2 = 1;
    //选出第一个权值最小的节点
    w = 100000;
    for (i = 1; i <= n; i++) {
        if (HT[i].parent == 0 && w > HT[i].weight) {
            w = HT[i].weight;
            s1 = i;
        }
    }
    //将权值初始值w重置最大,选出第二个权值最小的节点
    w = 100000;
    for (i = 1; i <= n; i++) {
        if (HT[i].parent == 0 && w > HT[i].weight && i != s1) {
            w = HT[i].weight;
            s2 = i;
        }
    }
}

//统计字符串str中各字符的个数
void Huffmans(int w[], char *str, int &n, char *a) {
    int i, j;
    n = 0;
    //将个数初始化为0
    for (j = 0; j < 60; j++) {
        w[j] = 0;
    }
    //遍历
    for (i = 0; str[i] != '\0'; i++) {
        if (str[i] == ' ') {
            w[52]++;
        } else {
            w[str[i] - 65]++;
        }
    }
    for (i = 0; i < 60; i++) {
        if (w[i] != 0) n++;
    }
    j = 0;
    for (i = 0; i < 60; i++) {
        if (w[i] != 0) {
            if (i == 52) {
                a[j] = ' ';
            } else {
                a[j] = i + 65;
            }
            j++;
        }
    }
    printf("\n");
}
//从1.txt中读取字符串

void inputfile(char *str) {
    int index = 0;
    char ch;
    FILE *fp;
    fp = fopen("1.txt", "r");
    while ((ch = fgetc(fp)) != EOF) {
        str[index++] = ch;
    }
    str[index] = '\0';
    fclose(fp);
}

//将编码后的字符写入到文件中
void outputfile(HuffmanCode HC, int n, char *a) {
    FILE *fp;
    int i, j;
    fp = fopen("1.txt", "a+");
    if (fp == 0) {
        printf("不能打开文件\n");
        return;
    }
    fseek(fp, 0, SEEK_END);        //设置文件指针
    for (i = 1; i <= n; i++) {
        fprintf(fp, "\n");
        fprintf(fp, "%c的编码: ", a[i - 1]);
        for (j = 0; j < n; j++) {
            if (HC[i][j] == '0' || HC[i][j] == '1') {
                fprintf(fp, "%c ", HC[i][j]);
            }
        }
    }
    fclose(fp);
}


int main() {
    HuffmanTree HT;
    HuffmanCode HC;      //定义哈夫曼树与哈夫曼编码
    char str[99999], a[60];
    int w[60];
    int n;
    inputfile(str);           //读入字符串
    printf("%s\n", str);      //将读取到的字符串输出
    Huffmans(w, str, n, a);      //统计该字符串中各字符的次数
    HuffmanCoding(HT, HC, w, n); //对这些字符进行编码
    printf("\n");
    outputfile(HC, n, a);      //将哈夫曼编码输出带文件中
    return 0;
}
posted @ 2022-06-30 14:03  WEIWEI1095  阅读(119)  评论(0)    收藏  举报
*/
作品集 //