Principes fondamentaux des structures de données et des algorithmes (Wang Zhuo) (23) : Codage de Huffman (2) : résultats

Table des matières

D'après l'étude de la section précédente, le résultat final écrit est le suivant :

Le résultat final de la modification est le suivant : (probablement la bonne réponse)

Parcours d'apprentissage personnel :

Projet 1:

question:

Projet 2 : (produit final)


D'après l'étude de la section précédente, le résultat final écrit est le suivant :

#include<iostream>
using namespace std;

struct HTNode
{
    int weight;
    int parent;
    int lchild, rchild;
};
typedef HTNode* HuffmanTree;
HuffmanTree HT;//既表示指针又表示整个数组

typedef int Status;

void Select(HuffmanTree& HT, int n, int& s1, int& s2)
{
    /*找第一个最小值*/
    int min;//用来存放最小值
    for (int i = 1; i <= n; i++)
    {
        if (HT[i].parent == 0)
        {
            min = i;
            break;
            //注意:这里我们的 break语句,让我们直接跳出for语句
        }
    }
    for (int i = min + 1; i <= n; i++)
    {
        if (HT[i].parent == 0 && HT[i].weight < HT[min].weight)
            min = i;
    }
    s1 = min; //第一个最小值给s1

    /*找第二个最小值*/
    for (int i = 1; i <= n; i++)
    {
        if (HT[i].parent == 0 && i != s1)
        {
            min = i;
            break;
        }
    }
    for (int i = min + 1; i <= n; i++)
    {
        if (HT[i].parent == 0 && HT[i].weight < HT[min].weight && i != s1)
            min = i;
    }
    s2 = min; //第二个最小值给s2
}

void CreateHuffmanTree(HuffmanTree& H, int n) //已知输入有n个结点
{
    //1、构造森林全是根
    int m = 2 * n - 1;
    //数组共2n-1个有效元素
    H = new HTNode[m + 1];
    //第0位空置
    for (int i = 1; i <= m; i++)
        H[i].lchild = H[i].parent = H[i].rchild = 0;
    for (int i = 1; i <= n; i++)
        //        H[i].weight = w[i - 1];
        cin >> H[i].weight;
    //   2、选用两小造新树;
    //   3、删除两小添新人;
    //   4、重复 2、3 剩单根
    int s1, s2;
    for (int i = n + 1; i <= m; i++)
    {
        Select(H, i - 1, s1, s2);
        H[i].weight = H[s1].weight + H[s2].weight;
        H[s1].parent = H[s2].parent = i;
        //如何限制让这两个已经被取出来使用过的元素在后面的循环不再被使用:
        //在Select函数里面添加限制条件:
        //我们只筛选比较选中范围内parent属性为0的元素
        H[i].lchild = s1;
        H[i].rchild = s2;
    }
}


typedef char **HuffmanCode;
//typedef char** HuffmanCode;

void CreatHuffmanCode(HuffmanTree HT, HuffmanCode& HC, int n)
{
    HC = new char *[n + 1];  
    char* cd = new char[n];
    cd[n] = '\0';
    //逐字符求Huffman编码

    for (int i = 1; i <= n; i++)
    {    
        int np = n;//now point
        int pp = HT[i].parent;//parent point
        int insert = n - 1;//inser:插入

        while (HT[pp].parent != 0)
        {
            //每输入cd表1次,下次输入就向前指一个位置
            insert--;

            //往cd的最后面一位输入:左0右1
            if (HT[pp].lchild == i)
                cd[n - 1] = 0;
            else
                cd[n - 1] = 1;

            //把比较使用的结点改成parent的结点,然后进入下一轮的循环和比较
            np = pp;
            pp = HT[np].parent;
        }
        HC[i] = new char[n - insert];
        strcpy(HC[i], &cd[insert]); 
    }
    delete[]cd;
}

int main()
{

}

Mais cette chose signale toujours une erreur :

je suis vraiment sans voix,


Enfin, dans la zone de commentaire du cours en ligne du professeur, j'ai vu un exemple d'implémentation de l'algorithme avec une pile sur Github, mais il n'y a qu'un corps de fonction, et les paramètres de variable sont un peu étranges

Le résultat final de la modification est le suivant : (probablement la bonne réponse)

//顺序栈
#include<iostream>
using namespace std;

#define TRUE        1
#define FALSE       0
#define OK          1
#define ERROR       0
#define INFEASIBLE  -1
//#define OVERFLOW   -2   

#define MAXlength 100  
//可按需修改,PPT中写的是MAXlength

typedef int Status;
typedef int SElemType;
//注意:这一段必须写在调用SElemType类型及其指针之前

struct SqStack
{
    SElemType* base; //栈底指针  
    SElemType* top;//栈顶指针
    int stacksize; //栈可用最大容量
};

Status InitStack(SqStack& S)//构造一个空栈
{
    S.base = new SElemType[MAXlength];
    //或
    //S.base = (SElemType*)malloc(MAXlength * sizeof(SElemType));
    if (!S.base) exit(OVERFLOW);// 存储分配失败
    S.top = S.base;
    //栈顶指针等于栈底指针
    S.stacksize = MAXlength;
    return true;
}

Status StackEmpty(SqStack S)
{
    // 若栈为空,返回TRUE;否则返回FALSE 
    if (S.top == S.base)
        return TRUE;
    else
        return FALSE;
}

int StackLength(SqStack S)
{
    return S.top - S.base;
}

Status ClearStack(SqStack S)//清空顺序栈
{
    if (S.base)
        S.top = S.base;
    return OK;
}

Status DestroyStack(SqStack& S)//销毁
{
    if (S.base)
    {
        delete S.base;
        S.stacksize = 0;
        S.base = S.top = NULL;
    }
    return OK;
}

Status Push(SqStack& S, SElemType e)
{
    if (S.top - S.base == S.stacksize)
        //不是MAXlength
        return OVERFLOW;
    *S.top = e;
    S.top++;
    //也可以写成:
    //*S.top++ = e;
    return true;
}

Status Pop(SqStack& S, SElemType& e)
//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;	否则返回ERROR
{
    if (S.top == S.base) // 等价于 if(StackEmpty(S))
        return UNDERFLOW;//ERROR;
    e = *S.top;
    S.top--;
    //e = *--S.top;
    return true;
}

struct HTNode
{
    int weight;
    int parent;
    int lchild, rchild;
};
typedef HTNode* HuffmanTree;
HuffmanTree HT;//既表示指针又表示整个数组

void Select(HuffmanTree& HT, int n, int& s1, int& s2)
{
    /*找第一个最小值*/
    int min;//用来存放最小值
    for (int i = 1; i <= n; i++)
    {
        if (HT[i].parent == 0)
        {
            min = i;
            break;
            //注意:这里我们的 break语句,让我们直接跳出for语句
        }
    }
    for (int i = min + 1; i <= n; i++)
    {
        if (HT[i].parent == 0 && HT[i].weight < HT[min].weight)
            min = i;
    }
    s1 = min; //第一个最小值给s1

    /*找第二个最小值*/
    for (int i = 1; i <= n; i++)
    {
        if (HT[i].parent == 0 && i != s1)
        {
            min = i;
            break;
        }
    }
    for (int i = min + 1; i <= n; i++)
    {
        if (HT[i].parent == 0 && HT[i].weight < HT[min].weight && i != s1)
            min = i;
    }
    s2 = min; //第二个最小值给s2
}

void CreateHuffmanTree(HuffmanTree& H, int n) //已知输入有n个结点
{
    //1、构造森林全是根
    int m = 2 * n - 1;
    //数组共2n-1个有效元素
    H = new HTNode[m + 1];
    //第0位空置
    for (int i = 1; i <= m; i++)
        H[i].lchild = H[i].parent = H[i].rchild = 0;
    for (int i = 1; i <= n; i++)
        //        H[i].weight = w[i - 1];
        cin >> H[i].weight;
    //   2、选用两小造新树;
    //   3、删除两小添新人;
    //   4、重复 2、3 剩单根
    int s1, s2;
    for (int i = n + 1; i <= m; i++)
    {
        Select(H, i - 1, s1, s2);
        H[i].weight = H[s1].weight + H[s2].weight;
        H[s1].parent = H[s2].parent = i;
        //如何限制让这两个已经被取出来使用过的元素在后面的循环不再被使用:
        //在Select函数里面添加限制条件:
        //我们只筛选比较选中范围内parent属性为0的元素
        H[i].lchild = s1;
        H[i].rchild = s2;
    }
}

void HuffmanCode(HuffmanTree& H, const int n)
{
    //第一步:调用函数创建一个顺序存储结构的哈夫曼树,同上的函数一样
    CreateHuffmanTree(H, n);
    //第二步:遍历哈夫曼树中每一个叶子结点,也即哈夫曼数组中的前n个元素
    for (int i = 1; i <= n; ++i)
    {
        int np = n;//now point
        int pp = HT[np].parent;//parent point
        int insert = n - 1;//inser:插入
        SqStack S;
        InitStack(S);//用栈来保存

        while (np != 0)
        {
            H[pp].lchild == np ? /*0进栈*/ Push(S, 0) : /*1进栈*/ Push(S, 1);
            np = pp;
            pp = H[np].parent;
        }
        //出栈//黑框中打印编码
        while (!StackEmpty(S))
        {
            int out;
            Pop(S, out);
            cout << out;
        }
        cout << endl;
    }
}


int main()
{

}

Alors frères, vous devez toujours avoir la capacité de penser de manière indépendante

La méthode de cours en ligne n'est pas forcément la bonne, c'est la meilleure

Au final, il n'est pas nécessaire de s'appuyer sur la pile pour réaliser


Parcours d'apprentissage personnel :

Ensuite, écrivez-le silencieusement et déchirez-le à nouveau : (n'écrivez que le corps de la fonction)

Projet 1:

void HuffmanCode(HuffmanTree& H, int n)//用栈实现
{
    CreateHuffmanTree(H, n);

    for (int i; i <= n; i++)
    {
        int NowP = i;
        int ParentP = H[NowP].parent;
        
        SqStack S;
        InitStack(S);

        while (ParentP != 0)
        {
            H[ParentP].lchild = NowP ? Push(S, 0) : Push(S, 1);

            NowP = ParentP;
            ParentP = H[ParentP].parent;
        }
        cout << "当叶子序号为" << i << "时,哈夫曼编码为:" << endl;
        while(!StackEmpty(S))
            Pop(S, i);
        ClearStack(S);//清空顺序栈
    }
    
}

question:

(1):

La variable insert n'est pas écrite ;
insert : indique (enregistre) le numéro de position correspondant de chaque branche (arête) que nous saisissons dans la table cd

Cependant, peu importe si nous ne l'écrivons pas ici, il semble que nous n'ayons pas à nous en soucier lorsque nous utilisons la pile pour réaliser le code de Huffman.

(2):

Il devrait être de sauter au nœud numéro 0 pour terminer la boucle au lieu de :

        tant que (ParentP != 0)

(3):

Dans la sortie finale, le i-ème code Huffman doit être sorti un par un, et le programme doit être réécrit

(4):

Il n'y a pas de valeur initiale assignée au i de la boucle for dans le programme


Projet 2 : (produit final)

void HuffmanCode(HuffmanTree& H, int n)//用栈实现
{
    CreateHuffmanTree(H, n);

    for (int i = 1; i <= n; i++)
    {
        int NowP = i;
        int ParentP = H[NowP].parent;
        
        SqStack S;
        InitStack(S);

        while (NowP != 0)
        {
            H[ParentP].lchild = NowP ? Push(S, 0) : Push(S, 1);

            NowP = ParentP;
            ParentP = H[ParentP].parent;
        }
        cout << "当叶子序号为" << i << "时,哈夫曼编码为:" << endl;
        while (!StackEmpty(S))
        {
            int a;
            Pop(S, a);
            cout << a;
        }
        cout << endl;
        ClearStack(S);//清空顺序栈
    }
}

ENDL

Je suppose que tu aimes

Origine blog.csdn.net/Zz_zzzzzzz__/article/details/129929995
conseillé
Classement