数据结构实训——哈夫曼(Huffman)编/译码器

题目4、哈夫曼(Huffman)编/译码器(限1人完成)

【问题描述】

利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站写一个哈夫曼码的编/译码系统。首先输入一段包含27个字符(包含空格)的文字(可以存在一个文件中),然后统计出各个字符出现的次数,以每个字符出现的次数为权值构造哈夫曼树,求得哈夫曼编码。

【基本要求】

一个完整的系统应具有以下功能:
1、 O: 输入一段字符(要包含27各字符)存入文件chartexfile中,统计出各个字符出现的次数并以表格的形式存入文件charsumfile中.
例如如下表:

字符空格ABCDEFGHIJKLM
频度1866413223210321154757153240
字符NOPQRSTUVWXYZ
频度5763151485180238181161

2、I:初始化(Initialization)。从终端读入字符集大小n,n个字符及n个权值,建立哈夫曼树,并将它存于文件hfmTree中。
3、 E:编码(Encoding)。利用以建好的哈夫曼树(如不在内存,则从文件hfmTree中读入),
对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
4、D:译码(Decoding)。利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。
5. P:打印代码文件(Print)。将文件CodeFile以紧凑格式显示在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件CodePrin中。
4、 T:打印哈夫曼树(Tree Printing)。将已在内存中的哈夫曼树以直观的方式(树或凹入
表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。
【测试数据】
用文件charsumfile给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:“THIS PROGRAM IS MY FAVORITE”。
测试数据要求:
要求使用1、全部合法数据;2、整体非法数据;3、局部非法数据。进行程序测试,以保证程序的稳定

附上代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

struct HuffmanTree
{
    int weight;                 //结点的权值
    int Lchild, Rchild, Parent; //存放左右结点,父结点下标
    char letter;                //存放所表示的字符
};

struct code
{
    char col[28]; //存放编码
    char letter;  //存放所表示的字符
} HC[28];         //0号单元无用

struct HuffmanTree *HT = NULL; //哈夫曼树结点
int N;                         //全局变量存字符个数

void Input();                         //输入字符函数声明
void Init();                          //初始化函数声明
void CreateHTree(char a[], int w[]);  //建立哈夫曼树声明
void Select(int n, int *s1, int *s2); //从1-n选择权值最小的两个元素下标
void PutHuffmanTree();                //打印哈夫曼树表
void CreateHuffmanCode();             //哈夫曼编码
void Puteverycode();                  //输出每个字符的编码情况
int FILEhfmtree();                    //从文件中读取哈夫曼树
void Codetxt();                       //编码文件
void DeCodetxt();                     //译码文件
void Printcodetxt();                  //打印编码生成的文件
void Printhftree();                   //打印哈夫曼树表

int main()
{
    int i, j;
    char command;
    system("color 0f");
    while (1)
    {
        printf("哈夫曼编译码器\n\n");
        printf("O: 输入一段字符(包含26个大写字母和空格),统计出各个字符出现的次数\n\n");
        printf("I:初始化,建立哈夫曼树\n\n");
        printf("E:编码(Encoding)\n\n");
        printf("D:译码(Decoding)\n\n");
        printf("P:打印代码文件(Print)\n\n");
        printf("T:打印哈夫曼树(Tree Printing)\n\n");
        printf("Q:退出程序\n\n");
        printf("请输入一个字母选择功能:");
        scanf("%c", &command);
        fflush(stdin);
        if ('Q' == command || 'q' == command)
            break;
        switch (command)
        {
        case 'o':
        case 'O':
            Input();
            break;
        case 'i':
        case 'I':
            Init();
            break;
        case 'e':
        case 'E':
            Codetxt();
            break;
        case 'd':
        case 'D':
            DeCodetxt();
            break;
        case 'p':
        case 'P':
            Printcodetxt();
            break;
        case 't':
        case 'T':
            Printhftree();
            break;
        default:
            printf("输入的命令有误!\n");
            system("pause");
            system("cls");
            break;
        }
    }
    system("pause");
    return 0;
}
void Input()
{ //输入字符串函数
    char str[1024], a[27] = " ";
    int Alph[27], i, j, flag = 1;
    FILE *fp;
    memset(Alph, 0, 27 * sizeof(int));
    printf("请输入一串必须包含26个大写英文字母和空格的字符串\n");
    printf("Tip:输入以回车结束\n");
    gets(str);
    i = 0;
    while (str[i])
    {
        if ('A' <= str[i] && str[i] <= 'Z')
            Alph[str[i] - 'A' + 1] += 1;
        else if (str[i] == ' ')
            Alph[0] += 1;
        else
        {
            flag = 0;
            printf("输入字符串有不合条件的字符,请退出后重试!\n");
            break;
        }
        i++;
    }
    if (flag)
    {
        if (!Alph[0])
        {
            flag = 0;
            printf("输入的字符串不包含  空格\n");
        }
        for (i = 1; i < 27; i++)
            if (!Alph[i])
            {
                flag = 0;
                printf("输入的字符串不包含  %c\n", i + 64);
            }
        if (!flag)
            printf("请退出后重新输入\n");
    }
    if (flag)
    {
        fp = fopen("chartexfile.txt", "w");
        if (fp == NULL)
        {
            printf("创建文件chartexfile.txt错误\n");
            system("pause");
            system("cls");
            return;
        }
        fputs(str, fp);
        fclose(fp);
        printf("\n字符串已经写入chartexfile.txt文件\n\n");
        fp = fopen("charsumfile.txt", "w");
        if (fp == NULL)
        {
            printf("创建文件charsumfile.txt错误\n");
            system("pause");
            system("cls");
            return;
        }
        fprintf(fp, "%c%d", '@', Alph[0]); //用@代替空格方便后面读数据
        printf("字符  空格");
        for (i = 1; i < 27; i++)
            printf("%3c", i + 64);
        printf("\n频度  %4d", Alph[0]);
        for (i = 1; i < 27; i++)
        {
            fprintf(fp, "\n%c%d", i + 64, Alph[i]);
            printf("%3d", Alph[i]);
        }
        printf("\n\n各字符出现次数已经写入charsumfile.txt文件\n");
        fclose(fp);
        printf("\n是否使用上面的字符和频度生产哈夫曼树?(Y/N)");
        if ('Y' == fgetc(stdin))
        {
            for (i = 1; i < 27; i++)
                a[i] = i + 64;
            N = 27;
            CreateHTree(a, Alph);
            PutHuffmanTree();
            CreateHuffmanCode();
            Puteverycode();
        }
    }
    system("pause");
    system("cls");
    fflush(stdin);
}

void Init()
{ //初始化函数
    int i, flag, com;
    FILE *fp;
    char ABC[27], temp;
    int ABCnums[27];
    int filenums[27];
    system("cls");
    printf("1.输入字符从charsumfile.txt中读取频度\n\n");
    printf("2.输入字符和频度\n\n");
    printf("输入一个数选择功能:");
    flag = scanf("%d", &com);
    while (flag != 1 || com > 2 || com < 1)
    {
        printf("输入指令不对,请重新输入\n");
        fflush(stdin);
        flag = scanf("%d", &com);
    }
    printf("\n请输入字符集大小N, 1<= N <=27\n");
    flag = scanf("%d", &N);
    while (flag != 1 || N < 1 || N > 27)
    {
        printf("输入指令不对,请重新输入\n");
        fflush(stdin);
        flag = scanf("%d", &N);
    }
    if (com == 1)
    {
        fp = fopen("charsumfile.txt", "r");
        if (fp == NULL)
        {
            printf("charsumfile.txt读取错误\n");
            system("pause");
            system("cls");
            return;
        }
        for (i = 0; i < 27; i++)
            fscanf(fp, "%c%d\n", &temp, &filenums[i]);
        fclose(fp);
        printf("\n请输入N个不同的大写字母或空格,输入一个按一下回车\n");
        for (i = 0; i < N; i++)
        {
            fflush(stdin);
            ABC[i] = getc(stdin);
            while ((ABC[i] > 'Z' || ABC[i] < 'A') && ABC[i] != ' ')
            {
                printf("输入的不是大写字母或空格,请重新输入\n");
                fflush(stdin);
                ABC[i] = getc(stdin);
            }
            if (ABC[i] == ' ')
                ABCnums[i] = filenums[0];
            else
                ABCnums[i] = filenums[ABC[i] - 64];
        }
    }
    else if (com == 2)
    {
        printf("\n输入大写字母或空格和频度例如\nA12\nC23\n\n");
        for (i = 0; i < N; i++)
        {
            fflush(stdin);
            ABC[i] = getc(stdin);
            scanf("%d", &ABCnums[i]);
        }
    }
    printf("字符  ");
    for (i = 0; i < N; i++)
    {
        if (ABC[i] == ' ')
            printf("空格 ");
        else
            printf("%-4c ", ABC[i]);
    }
    printf("\n频度  ");
    for (i = 0; i < N; i++)
        printf("%-4d ", ABCnums[i]);
    printf("\n");
    CreateHTree(ABC, ABCnums); //建立哈夫曼树
    PutHuffmanTree();          //输出哈夫曼树表
    fp = fopen("hfmTree.txt", "w");
    if (fp == NULL)
    {
        printf("hfmTree.txt文件创建错误\n");
        system("pause");
        system("cls");
        return;
    }
    fprintf(fp, "%-6s%-6s%-6s%-8s%-8s%-6s\n", "编号", "字符", "权值", "左孩子", "右孩子", "父亲");
    for (i = 1; i <= N; i++)
    {
        if (HT[i].letter == ' ') //空格用@代替,方便读文件
            fprintf(fp, "%-6d%-6c%-6d%-8d%-8d%-6d\n", i, '@', HT[i].weight, HT[i].Lchild, HT[i].Rchild, HT[i].Parent);
        else
            fprintf(fp, "%-6d%-6c%-6d%-8d%-8d%-6d\n", i, HT[i].letter, HT[i].weight, HT[i].Lchild, HT[i].Rchild, HT[i].Parent);
    }
    for (i; i <= 2 * N - 1; i++)
        fprintf(fp, "%-6d%-6c%-6d%-8d%-8d%-6d\n", i, HT[i].letter, HT[i].weight, HT[i].Lchild, HT[i].Rchild, HT[i].Parent);
    fclose(fp);
    printf("\n哈夫曼树表已经写入hfmTree.txt中\n");
    CreateHuffmanCode(); //哈夫曼编码
    Puteverycode();      //输出每个字符编码的情况
    system("pause");
    system("cls");
    fflush(stdin);
}

void CreateHTree(char a[], int w[])
{ //建立哈夫曼树
    struct HuffmanTree *pt;
    int m, i, s1, s2;
    m = 2 * N - 1;
    s1 = 1;
    s2 = 2;
    HT = (struct HuffmanTree *)malloc(sizeof(struct HuffmanTree) * (m + 1));
    //0号单元未使用
    pt = HT;                                 /*HT指向0号单元*/
    pt++;                                    //pt指向下标为1的单元
    for (i = 1; i <= N; i++, pt++, w++, a++) //数组1-n分量初始化
    {
        pt->weight = *w;
        pt->Lchild = 0;
        pt->Rchild = 0;
        pt->Parent = 0;
        pt->letter = *a;
    }
    for (i; i <= m; i++, pt++) //数组n+1~2n-1分量初始化
    {
        pt->weight = 0;
        pt->Lchild = 0;
        pt->Rchild = 0;
        pt->Parent = 0;
        pt->letter = 0;
    }
    for (i = N + 1; i <= m; i++) //构造哈夫曼树
    {
        Select(i - 1, &s1, &s2); //在HT[1..i-1]中选择parent为0且weight最小的两个结点,序号为s1,s2
        HT[i].Lchild = s1;
        HT[i].Rchild = s2;
        HT[i].weight = HT[s1].weight + HT[s2].weight;
        HT[s1].Parent = i;
        HT[s2].Parent = i;
    }
}

void Select(int n, int *s1, int *s2)
{ //从1~n之间选择权值最小的两个元素下标
    int i = 1, temp;
    while (HT[i].Parent != 0 && i <= n) //寻找第一个未访问的元素下标
        i++;
    if (i == n + 1)
        return;
    *s1 = i++;
    while (HT[i].Parent != 0 && i <= n) //寻找第二个未访问的元素下标
        i++;
    if (i == n + 1)
        return;
    *s2 = i++;
    if (HT[*s1].weight > HT[*s2].weight)
    {
        temp = *s1;
        *s1 = *s2;
        *s2 = temp;
    }
    for (; i <= n; i++) //选取两个最小权值
    {
        if (HT[i].Parent == 0)
        {
            if (HT[i].weight < HT[*s1].weight)
            {
                *s2 = *s1;
                *s1 = i;
            }
            else if (HT[i].weight < HT[*s2].weight)
                *s2 = i;
        }
    }
}

void PutHuffmanTree()
{ //打印哈夫曼树表
    int i, m = 2 * N - 1;
    printf("\n输出哈夫曼树表\n");
    printf("\n%-6s%-6s%-6s%-8s%-8s%-6s\n", "编号", "字符", "权值", "左孩子", "右孩子", "父亲");
    for (i = 1; i <= N; i++)
    {
        if (HT[i].letter == ' ')
            printf("%-6d%-6s%-6d%-8d%-8d%-6d\n", i, "空格", HT[i].weight, HT[i].Lchild, HT[i].Rchild, HT[i].Parent);
        else
            printf("%-6d%-6c%-6d%-8d%-8d%-6d\n", i, HT[i].letter, HT[i].weight, HT[i].Lchild, HT[i].Rchild, HT[i].Parent);
    }
    for (i; i <= m; i++)
        printf("%-6d%-6c%-6d%-8d%-8d%-6d\n", i, HT[i].letter, HT[i].weight, HT[i].Lchild, HT[i].Rchild, HT[i].Parent);
    printf("\n");
}

void CreateHuffmanCode()
{ //哈夫曼编码
    int start, i, p, f;
    char col[28];
    memset(HC, 0, sizeof(struct code) * 28);
    for (i = 1; i <= N; i++) //逐个字符求编码
    {
        memset(col, 0, sizeof(col));
        start = N - 1; //编码结束符位置
        p = f = i;
        while (HT[f].Parent != 0) //从叶子到根逆向求编码
        {
            f = HT[f].Parent;
            if (HT[f].Lchild == p)
                col[--start] = '0';
            else if (HT[f].Rchild == p)
                col[--start] = '1';
            p = f;
        }
        HC[i].letter = HT[i].letter;
        strcpy(HC[i].col, col + start);
    }
}

void Puteverycode()
{ //输出每个字符的编码情况
    int i;
    printf("%-6s%-8s\n", "字符", "编码");
    for (i = 1; i <= N; i++)
    {
        if (HC[i].letter == ' ')
            printf("%-6s%-8s\n", "空格", HC[i].col);
        else
            printf("%-6c%-8s\n", HC[i].letter, HC[i].col);
    }
}

int FILEhfmtree()
{ //从文件中读取哈夫曼树
    FILE *fp;
    int i, temp;
    char a;
    fp = fopen("hfmTree.txt", "r");
    if (fp == NULL)
        return 0;
    getc(fp);
    if (feof(fp))
        return 0;
    i = 1;
    while (1)
    {
        fseek(fp, 42 * i + 6, SEEK_SET);
        a = fgetc(fp);
        if (!a)
            break;
        i++;
    }
    N = i - 1;
    HT = (struct HuffmanTree *)malloc(sizeof(struct HuffmanTree) * (2 * N));
    for (i = 1; i <= 2 * N - 1; i++)
    {
        fseek(fp, 42 * i + 6, SEEK_SET);
        a = fgetc(fp);
        fscanf(fp, "%d%d%d%d", &HT[i].weight, &HT[i].Lchild, &HT[i].Rchild, &HT[i].Parent);
        if (a == '@')
            HT[i].letter = ' ';
        else
            HT[i].letter = a;
    }
    fclose(fp);
    return 1;
}

void Codetxt()
{ //编码文件
    char str[1024];
    char codehf[2048];
    int i, j;
    FILE *fp;
    system("cls");
    if (NULL == HT)
    {
        printf("\n当前内存中没有哈夫曼树,是否从hfmTree.txt文件读取(Y/N)\n");
        fflush(stdin);
        if ('Y' == getc(stdin))
        {
            if (FILEhfmtree() == 0)
            {
                printf("\nhfmTree.txt中没有哈夫曼树,请使用功能I初始化\n");
                system("pause");
                system("cls");
                fflush(stdin);
                return;
            }
        }
        else
        {
            printf("\n没有构建哈夫曼树,无法进行编码\n");
            system("pause");
            system("cls");
            fflush(stdin);
            return;
        }
    }
    CreateHuffmanCode();
    if (NULL == (fp = fopen("ToBeTran.txt", "w")))
    {
        printf("\nToBeTran.txt文件创建错误\n");
        system("pause");
        system("cls");
        return;
    }
    printf("\n请使用这些字符:  ");
    for (i = 1; i <= N; i++)
    {
        if (HC[i].letter == ' ')
            printf("%-5s", "空格");
        else
            printf("%-5c", HC[i].letter);
    }
    printf("\n\n请输入一串要编码的文本\n");
    fflush(stdin);
    gets(str);
    fputs(str, fp);
    fclose(fp);
    printf("\n输入的文本已经存入ToBeTran.txt文件\n");
    memset(codehf, 0, sizeof(codehf));
    for (i = 0; str[i]; i++)
    {
        for (j = 1; j <= N; j++)
            if (str[i] == HC[j].letter)
            {
                strcat(codehf, HC[j].col);
                break;
            }
        if (j == N + 1)
        {
            printf("\n有不能编码的字符:%c\n退出后重试\n", str[i]);
            system("pause");
            system("cls");
            return;
        }
    }
    printf("\n编码结果:\n");
    for (i = 0; codehf[i]; i++)
    {
        printf("%c", codehf[i]);
        if (i % 50 == 49)
            printf("\n");
    }
    if (NULL == (fp = fopen("CodeFile.txt", "w")))
    {
        printf("\nCodeFile.txt文件创建错误\n");
        system("pause");
        system("cls");
        return;
    }
    fputs(codehf, fp);
    fclose(fp);
    printf("\n编码结果已经存入CodeFile.txt文件\n");
    system("pause");
    system("cls");
    fflush(stdin);
}

void DeCodetxt()
{ //译码文件
    char str[1024];
    char codehf[2048];
    int i, j, start, temp;
    FILE *fp;
    system("cls");
    if (NULL == HT)
    {
        printf("\n当前内存中没有哈夫曼树,是否从hfmTree.txt文件读取(Y/N)\n");
        fflush(stdin);
        if ('Y' == getc(stdin))
        {
            if (FILEhfmtree() == 0)
            {
                printf("\nhfmTree.txt中没有哈夫曼树,请使用功能I初始化\n");
                system("pause");
                system("cls");
                fflush(stdin);
                return;
            }
        }
        else
        {
            printf("\n没有构建哈夫曼树,无法进行译码\n");
            system("pause");
            system("cls");
            fflush(stdin);
            return;
        }
    }
    CreateHuffmanCode();
    printf("\n当前的哈夫曼树中:\n");
    Puteverycode();
    if (NULL == (fp = fopen("CodeFile.txt", "r")))
    {
        printf("\nCodeFile.txt文件读取错误\n");
        system("pause");
        system("cls");
        return;
    }
    fgets(codehf, 2048, fp);
    fclose(fp);
    printf("\nCodeFile.txt文件源码中: \n");
    for (i = 0; codehf[i]; i++)
    {
        printf("%c", codehf[i]);
        if (i % 50 == 49)
            printf("\n");
    }
    memset(str, 0, sizeof(str));
    i = 0;
    for (j = 0;; j++)
    {
        start = 2 * N - 1;
        for (i; codehf[i]; i++)
        {
            if (codehf[i] == '0')
                temp = HT[start].Lchild;
            else if (codehf[i] == '1')
                temp = HT[start].Rchild;
            start = temp;
            if (HT[start].Lchild == 0 && HT[start].Rchild == 0)
            {
                i++;
                break;
            }
        }
        str[j] = HT[start].letter;
        if (codehf[i] == 0)
            break;
    }
    printf("\n\n译码结果:\n");
    for (i = 0; str[i]; i++)
    {
        printf("%c", str[i]);
        if (i % 50 == 49)
            printf("\n");
    }
    if (NULL == (fp = fopen("TextFile.txt", "w")))
    {
        printf("\nTextFile.txt文件创建错误\n");
        system("pause");
        system("cls");
        return;
    }
    fputs(str, fp);
    fclose(fp);
    printf("\n\n译码结果已经存入TextFile.txt文件中\n");
    system("pause");
    system("cls");
    fflush(stdin);
}

void Printcodetxt()
{//打印编码文件
    char codehf[2048];
    int i;
    FILE *fp;
    if (NULL == (fp = fopen("CodeFile.txt", "r")))
    {
        printf("\nCodeFile.txt文件读取错误\n");
        system("pause");
        system("cls");
        return;
    }
    fgets(codehf, 2048, fp);
    fclose(fp);
    if (NULL == (fp = fopen("CodePrin.txt", "w")))
    {
        printf("\nCodePrin.txt文件生成错误\n");
        system("pause");
        system("cls");
        return;
    }
    printf("\nCodeFile.txt文件内容:\n");
    for (i = 0; codehf[i]; i++)
    {
        fputc(codehf[i], fp);
        printf("%c", codehf[i]);
        if (i % 50 == 49)
        {
            printf("\n");
            fputc('\n', fp);
        }
    }
    fclose(fp);
    printf("\n\n每行50个编码的文件已经写入CodePrin.txt文件\n");
    system("pause");
    system("cls");
}

void Printhftree()
{ //打印哈夫曼树到文件
    int i, m = 2 * N - 1;
    FILE *fp;
    if (HT == NULL)
    {
        printf("\n当前内存中没有哈夫曼树\n");
        system("pause");
        system("cls");
        return;
    }
    printf("\n输出哈夫曼树表\n");
    printf("\n%-6s%-6s%-6s%-8s%-8s%-6s\n", "编号", "字符", "权值", "左孩子", "右孩子", "父亲");
    for (i = 1; i <= N; i++)
    {
        if (HT[i].letter == ' ')
            printf("%-6d%-6s%-6d%-8d%-8d%-6d\n", i, "空格", HT[i].weight, HT[i].Lchild, HT[i].Rchild, HT[i].Parent);
        else
            printf("%-6d%-6c%-6d%-8d%-8d%-6d\n", i, HT[i].letter, HT[i].weight, HT[i].Lchild, HT[i].Rchild, HT[i].Parent);
    }
    for (i; i <= m; i++)
        printf("%-6d%-6c%-6d%-8d%-8d%-6d\n", i, HT[i].letter, HT[i].weight, HT[i].Lchild, HT[i].Rchild, HT[i].Parent);
    printf("\n");

    if (NULL == (fp = fopen("TreePrint.txt", "w")))
    {
        printf("TreePrint.txt文件创建错误\n");
        system("pause");
        system("cls");
        return;
    }
    fprintf(fp, "%-6s%-6s%-6s%-8s%-8s%-6s\n", "编号", "字符", "权值", "左孩子", "右孩子", "父亲");
    for (i = 1; i <= N; i++)
    {
        if (HT[i].letter == ' ') //空格用@代替,方便读文件
            fprintf(fp, "%-6d%-6c%-6d%-8d%-8d%-6d\n", i, '@', HT[i].weight, HT[i].Lchild, HT[i].Rchild, HT[i].Parent);
        else
            fprintf(fp, "%-6d%-6c%-6d%-8d%-8d%-6d\n", i, HT[i].letter, HT[i].weight, HT[i].Lchild, HT[i].Rchild, HT[i].Parent);
    }
    for (i; i <= 2 * N - 1; i++)
        fprintf(fp, "%-6d%-6c%-6d%-8d%-8d%-6d\n", i, HT[i].letter, HT[i].weight, HT[i].Lchild, HT[i].Rchild, HT[i].Parent);
    fclose(fp);
    printf("\n哈夫曼树表已经写入TreePrint.txt中\n");
    system("pause");
    system("cls");
}
哈夫曼码译码 包括默认码 和 自定义数据结构课程设计 一、题目: 哈夫曼码/译码的设计与实现 二、目的与要求 1、目的: 通过布置具有一定难度的实际程序设计项目,使学生进一步理解和掌握课堂上所学各种基本抽象数据类型的逻辑结构、存储结构和操作实现算法,以及它们在程序中的使用方法;使学生掌握分析问题,求解问题的方法并提高学生设计程实现的能力。 2、要求: 基本要求: 1. 要求利用C\C++语言来完成系统的设计; 2. 突出C语言的函数特征(以多个函数实现每一个子功能)或者C++语言面向对象的程思想; 3. 画出功能模块图; 4. 进行简单界面设计,能够实现友好的交互; 5. 具有清晰的程序流程图和数据结构的详细定义; 6. 熟练掌握C语言或者C++语言的各种操作。 创新要求: 在基本要求达到后,可进行创新设计,如系统用户功能控制,改进算法的实现,实现友好的人机交互等等 三、问题描述和求解方法: 首先根据给定的n个权值构造哈夫曼树。通过遍历此二叉树完成哈夫曼码。 四、解题过程 1. 分析程序的功能要求,划分程序功能模块。 2. 画出系统流程图。 3. 代码的写。定义数据结构和各个功能子函数。 4. 程序的功能调试。 5. 完成系统总结报告以及使用说明书 五、进度安排 此次课程设计时间为一周,分以下几个阶段完成: 1. 选题与搜集资料:每人选择一题,进行课程设计课题的资料搜集。 2. 分析与概要设计:根据搜集的资料,进行程序功能与数据结构分析,并选择合适的数据结构、并在此基础上进行实现程序功能的算法设计。 3. 程序设计:运用掌握C/C++语言写程序,实现各个模块功能。 4. 调试与测试:调试程序,并记录测试情况。 5. 完成课程设计报告。 6. 验收与评分:指导教师对每个同学的开发的系统进行综合验收,并由学院考核小组进行随机抽查评分。 六、撰写课程设计报告或课程设计总结 课程设计报告要求: 课程设计报告要求规范书写,应当包括如下6个部分: 1. 问题描述 2. 基本要求 3. 系统分析与设计 4. 测试数据及结果 5. 总结 6. 附录:源程序清单 七、答辩与评分标准: 1 、作业档: 50 分; 2 、基本功能和要求: 20 分; 2 、设计报告及使用说明书: 10 分; 3 、设置错误或者按照要求改变结果: 10 分; 4 、回答问题: 10 分。 八、参考资料 《数据结构(C语言版)》 网上相关资料(....略) printf("---------------------------------------------\n"); printf(" 哈夫曼码和译码 \n"); printf(" 1.使用默认初始化 \n"); printf(" 2.使用自定义初始化 \n"); printf(" 3.进行哈夫曼码 \n"); printf(" 4.进行哈夫曼译码 \n") ; printf(" 5.退出哈夫曼操作 \n"); printf(" 请输入1.2.3.4.5 \n"); printf(" ---------------------------------------------\n");
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值