最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言實(shí)現(xiàn)BMP圖像處理(哈夫曼編碼)

 更新時(shí)間:2021年10月25日 17:08:56   作者:傻不拉幾的程序員  
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)BMP圖像哈夫曼編碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

哈夫曼(Huffman)編碼是一種常用的壓縮編碼方法,是 Huffman 于 1952 年為壓縮文本文件建立的。它的基本原理是頻繁使用的數(shù)據(jù)用較短的代碼代替,較少使用的數(shù)據(jù)用較長(zhǎng)的代碼代替,每個(gè)數(shù)據(jù)的代碼各不相同。這些代碼都是二進(jìn)制碼,且碼的長(zhǎng)度是可變的。

下面給出具體的 Huffman 編碼算法:

(1) 首先統(tǒng)計(jì)出每個(gè)符號(hào)出現(xiàn)的頻率,上例 S0 到 S7 的出現(xiàn)頻率分別為 4/14,3/14,2/14,1/14,1/14,1/14,1/14,1/14。
(2) 從左到右把上述頻率按從小到大的順序排列。
(3) 每一次選出最小的兩個(gè)值,作為二叉樹的兩個(gè)葉子節(jié)點(diǎn),將和作為它們的根節(jié)點(diǎn),這兩個(gè)葉子節(jié)點(diǎn)不再參與比較,新的根節(jié)點(diǎn)參與比較。
(4) 重復(fù)(3),直到最后得到和為 1 的根節(jié)點(diǎn)。
(5) 將形成的二叉樹的左節(jié)點(diǎn)標(biāo) 0,右節(jié)點(diǎn)標(biāo) 1。把從最上面的根節(jié)點(diǎn)到最下面的葉子節(jié)點(diǎn)途中遇到的 0,1 序列串起來,就得到了各個(gè)符號(hào)的編碼。

產(chǎn)生 Huffman 編碼需要對(duì)原始數(shù)據(jù)掃描兩遍。第一遍掃描要精確地統(tǒng)計(jì)出原始數(shù)據(jù)中,每個(gè)值出現(xiàn)的頻率,第二遍是建立 Huffman 樹并進(jìn)行編碼。由于需要建立二叉樹并遍歷二叉樹生成編碼,因此數(shù)據(jù)壓縮和還原速度都較慢,但簡(jiǎn)單有效,因而得到廣泛的應(yīng)用。

第一步:實(shí)現(xiàn)哈夫曼編碼與解碼

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
 
// 結(jié)構(gòu)體
typedef struct Tree
{
 int weight; // 權(quán)值
 int id;     // 后面解碼用到
 struct Tree * lchild; // 左孩子
 struct Tree * rchild; // 右孩子
}TreeNode;
 
// 創(chuàng)建哈夫曼樹
TreeNode* createTree(int *arr, int n)
{
 int i, j;
 TreeNode **temp, *hufmTree;
 temp = (TreeNode**)malloc(sizeof(TreeNode*)*n); // 創(chuàng)建結(jié)構(gòu)體指針數(shù)組
 for (i = 0; i < n; ++i)
 {
  temp[i] = (TreeNode*)malloc(sizeof(TreeNode));
  temp[i]->weight = arr[i];
  temp[i]->lchild = temp[i]->rchild = NULL;
  temp[i]->id = i;
 }
 
 for (i = 0; i < n - 1; ++i)
 {
  int small1 = -1, small2; // 存儲(chǔ)最小權(quán)值的兩個(gè)節(jié)點(diǎn)
  for (j = 0; j < n; ++j)  // 第一步:找到最開始兩個(gè)非空節(jié)點(diǎn)
  {
   if (temp[j] != NULL && small1 == -1)
   {
    small1 = j;
    continue;
   }
   if (temp[j] != NULL)
   {
    small2 = j;
    break;
   }
  }
  for (j = small2; j < n; ++j) // 找到權(quán)值最小的兩個(gè)節(jié)點(diǎn),并將最小的序號(hào)賦給small1,次小的賦給small2
  {
   if (temp[j] != NULL)
   {
    if (temp[j]->weight < temp[small1]->weight)
    {
     small2 = small1;
     small1 = j;
    }
    else if (temp[j]->weight < temp[small2]->weight)
    {
     small2 = j;
    }
   }
  }
  hufmTree = (TreeNode*)malloc(sizeof(TreeNode));
  hufmTree->lchild = temp[small1];
  hufmTree->rchild = temp[small2];
  hufmTree->weight = temp[small1]->weight + temp[small2]->weight;
 
  temp[small1] = hufmTree;
  temp[small2] = NULL;
 }
 free(temp);
 return hufmTree;
}
 
// 前序遍歷
void PreOrderTraversal(TreeNode* hufmTree)
{
 if (hufmTree)
 {
  printf("%d", hufmTree->weight);
  PreOrderTraversal(hufmTree->lchild);
  PreOrderTraversal(hufmTree->rchild);
 }
}
 
// 哈夫曼編碼
void hufmTreeCode(TreeNode* hufmTree,int depth)
{
 static int code[10],i;
 
 if (hufmTree)
 {
  if (hufmTree->lchild == NULL && hufmTree->rchild == NULL)
  {
   int i=0;
   printf("權(quán)值為%d的節(jié)點(diǎn),哈夫曼編碼為:", hufmTree->weight);
   for (i = 0; i < depth; ++i)
   {
    printf("%d", code[i]);
   }
   printf("\n");
  }
  else
  {
   code[depth] = 0;
   hufmTreeCode(hufmTree->lchild, depth + 1);
   code[depth] = 1;
   hufmTreeCode(hufmTree->rchild, depth + 1);
  }
 }
}
 
// 哈夫曼解碼
// 思想:通過定位ID,找到源碼中的位置
void hufmTreeDecode(TreeNode* hufmTree, char a[],char st[])
{
 int i,arr[100];
 TreeNode* temp;
 for (i = 0; i < strlen(a); ++i) // 轉(zhuǎn)化字符串編碼為數(shù)組編碼
 {
  if (a[i] == '0')
   arr[i] = 0;
  else
   arr[i] = 1;
 }
 i = 0;
 while (i < strlen(a))
 {
  temp = hufmTree;
  while (temp->lchild != NULL && temp->rchild != NULL)
  {
   if (arr[i] == 0)
    temp = temp->lchild;
   else
    temp = temp->rchild;
   i++;
  }
  printf("%c", st[temp->id]);
 }
 printf("\n");
 free(temp);
}
 
int main()
{
 int i, n, arr[100];
 printf("輸入需要?jiǎng)?chuàng)建的節(jié)點(diǎn)個(gè)數(shù):\n");
 scanf("%d", &n);
 printf("輸入權(quán)值:\n");
 for (i = 0; i < n; ++i)
  scanf("%d", &arr[i]);
 
 printf("\n請(qǐng)輸入每個(gè)權(quán)值對(duì)應(yīng)的字符:\n");
 char st[100];
 scanf("%s",st);
 
 // 創(chuàng)建哈夫曼樹
 TreeNode* hufmTree;
 hufmTree = createTree(arr, n);
 
 // 哈夫曼編碼
 printf("\n哈夫曼編碼為:\n");
 hufmTreeCode(hufmTree, 0);
 
 // 遍歷
 printf("\n前序遍歷:\n");
 PreOrderTraversal(hufmTree);
 
 // 解碼
 printf("\n請(qǐng)輸入需要解碼的碼字:\n");
 char codeSt[100]; 
 scanf("%s",codeSt);
 printf("\n解碼的碼字為:\n");
 hufmTreeDecode(hufmTree, codeSt, st);
 
 free(hufmTree);
 system("pause");
 return 0;
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解如何將Spire.PDF for C++集成到C++程序中

    詳解如何將Spire.PDF for C++集成到C++程序中

    Spire.PDF for C++ 是一個(gè)專業(yè)的 PDF 庫,供開發(fā)人員在任何類型的 C++ 應(yīng)用程序中閱讀、創(chuàng)建、編輯和轉(zhuǎn)換 PDF 文檔,本文主要介紹了兩種不同的方式將 Spire.PDF for C++ 集成到您的 C++ 應(yīng)用程序中,希望對(duì)大家有所幫助
    2023-11-11
  • C++ vector類的模擬實(shí)現(xiàn)方法

    C++ vector類的模擬實(shí)現(xiàn)方法

    這篇文章主要介紹了C++ vector類的模擬實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • Qt6遠(yuǎn)程連接MySQL數(shù)據(jù)庫的簡(jiǎn)單易上手版

    Qt6遠(yuǎn)程連接MySQL數(shù)據(jù)庫的簡(jiǎn)單易上手版

    在Qt應(yīng)用程序里,可實(shí)現(xiàn)遠(yuǎn)程MySQL服務(wù)器的連接操作,本文就來介紹一下Qt6遠(yuǎn)程連接MySQL數(shù)據(jù)庫,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • Qt數(shù)據(jù)庫應(yīng)用之實(shí)現(xiàn)通用數(shù)據(jù)生成器

    Qt數(shù)據(jù)庫應(yīng)用之實(shí)現(xiàn)通用數(shù)據(jù)生成器

    有兩種應(yīng)用場(chǎng)景需要用到數(shù)據(jù)生成器,一種是需要測(cè)試數(shù)據(jù)庫性能,一種是隨機(jī)模擬生成一堆數(shù)據(jù),用來測(cè)試程序的性能。本文將利用Qt實(shí)現(xiàn)通用數(shù)據(jù)生成器,需要的可以參考一下
    2022-02-02
  • C語言實(shí)現(xiàn)鏈隊(duì)列基本操作

    C語言實(shí)現(xiàn)鏈隊(duì)列基本操作

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)鏈隊(duì)列基本操作,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • c++實(shí)現(xiàn)超簡(jiǎn)單的貪吃蛇游戲?qū)嵗榻B

    c++實(shí)現(xiàn)超簡(jiǎn)單的貪吃蛇游戲?qū)嵗榻B

    大家好,本篇文章主要講的是c++實(shí)現(xiàn)超簡(jiǎn)單的貪吃蛇游戲?qū)嵗榻B,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • C語言操作符進(jìn)階教程(表達(dá)式求值隱式類型轉(zhuǎn)換方法)

    C語言操作符進(jìn)階教程(表達(dá)式求值隱式類型轉(zhuǎn)換方法)

    這篇文章主要為大家介紹了C語言操作符進(jìn)階教程(表達(dá)式求值隱式類型轉(zhuǎn)換方法)
    2022-02-02
  • C語言實(shí)現(xiàn)五子棋小游戲

    C語言實(shí)現(xiàn)五子棋小游戲

    五子棋游戲是一款很經(jīng)典的智力游戲,只有學(xué)過編程語言的人,把五子棋的編程原理弄懂了,就能用自己熟悉的語言實(shí)現(xiàn)出來,在這里給大家分享,c語言五子棋源碼,僅供大家參考借鑒。
    2016-03-03
  • C++實(shí)現(xiàn)LeetCode(129.求根到葉節(jié)點(diǎn)數(shù)字之和)

    C++實(shí)現(xiàn)LeetCode(129.求根到葉節(jié)點(diǎn)數(shù)字之和)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(129.求根到葉節(jié)點(diǎn)數(shù)字之和),本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C++騎士游歷問題(馬踏棋盤)解析

    C++騎士游歷問題(馬踏棋盤)解析

    這篇文章主要為大家詳細(xì)介紹了C++騎士游歷問題的解答思路,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02

最新評(píng)論

六盘水市| 玉溪市| 荆门市| 奉贤区| 诸暨市| 关岭| 承德县| 浦江县| 波密县| 洛隆县| 温州市| 昌宁县| 霸州市| 务川| 高要市| 保德县| 苍南县| 潍坊市| 额尔古纳市| 瑞昌市| 格尔木市| 米脂县| 桐城市| 景德镇市| 韶关市| 水城县| 登封市| 马龙县| 甘谷县| 霍林郭勒市| 曲阳县| 东乌珠穆沁旗| 日土县| 镇坪县| 上饶市| 铁岭市| 高碑店市| 临夏市| 光山县| 瑞金市| 武汉市|