C语言---数据结构实验---哈夫曼树及哈夫曼编码的算法实现---图的基本操作

简介: C语言---数据结构实验---哈夫曼树及哈夫曼编码的算法实现---图的基本操作

写在前面

本篇实验代码非本人写,代码源自外部,经调试解决了部分warning和error后在本地vs上可以正常运行,如有运行失败可换至vs

未来会重构实现该两个实验


哈夫曼树及哈夫曼编码的算法实现

实验内容

内容要求:

1、初始化(Init):能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立哈夫曼树

2、建立编码表(CreateTable):利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。

3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出

4、译码(Decoding):利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。

测试数据:

输入字符串“thisprogramismyfavourite”,完成这28个字符的编码和译码。

代码实现

#include<iostream>
#include<string.h>
#include<queue>
#define MAX 10000 
using namespace std;
char a[100], buff[1024], p;
typedef struct
{
  char letter, * code;
  int weight;
  int parent, lchild, rchild;
}HTNode, * HuffmanTree;
int n;
char coding[100];
int Min(HuffmanTree& HT, int i)
{
  int j;
  int k = MAX;
  int flag=0;
  for (j = 0; j <= i; ++j)
  {
    if (HT[j].weight < k && HT[j].parent == 0)
    {
      k = HT[j].weight;
      flag = j;
    }
  }
  HT[flag].parent = 1;
  return flag;
}
void Select(HuffmanTree& HT, int i, int& s1, int& s2)
{
  s1 = Min(HT, i);
  s2 = Min(HT, i);
}
void CreateHuffmanTree(HuffmanTree& HT, char t[], int w[])
{
  int m;
  int i, s1, s2;
  if (n <= 1)
    return;
  m = 2 * n - 1; 
  HT = new HTNode[m + 1];
  for (i = 0; i < n; i++)
  {
    char arr[] = "0";
    char* pa = arr;
    HT[i].code = pa;
    HT[i].parent = 0;
    HT[i].lchild = -1;
    HT[i].rchild = -1;
    HT[i].letter = t[i];
    HT[i].weight = w[i];
  }
  for (i = n; i <= m; i++)
  {
    char arr[] = "0";
    char* pa = arr;
    HT[i].code = pa;
    HT[i].parent = 0;
    HT[i].lchild = -1;
    HT[i].rchild = -1;
    HT[i].letter = ' ';
    HT[i].weight = 0;
  }
  cout << "********************************" << endl;
  for (i = n; 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;
  }
}
void CreatHuffmanCode(HuffmanTree HT)
{
  int start, c, f;
  int i;
  char* cd = new char[n];
  cd[n - 1] = '\0';
  cout << "字符编码为:" << endl;
  for (i = 0; i < n; i++)
  {
    start = n - 1;
    c = i;
    f = HT[i].parent;
    while (f != 0) 
    {
      --start;
      if (HT[f].lchild == c) 
      {
        cd[start] = '0';
      }
      else 
      {
        cd[start] = '1';
      }
      c = f;
      f = HT[f].parent;
    }
    HT[i].code = new char[n - start];
    strcpy(HT[i].code, &cd[start]);
    cout << HT[i].letter << ":" << HT[i].code << endl;
  }
  delete[] cd;
}
void HuffmanTreeDecode(HuffmanTree HT, char cod[], int b)  
{
  char sen[100];
  char temp[50];
  char voidstr[] = " ";
  int t = 0;
  int s = 0;
  int count = 0;
  for (int i = 0; i < b; i++)
  {
    temp[t++] = cod[i];
    temp[t] = '\0';
    for (int j = 0; j < n; j++) 
    {
      if (!strcmp(HT[j].code, temp)) 
      {
        sen[s] = HT[j].letter;
        s++;
        count += t;
        strcpy(temp, voidstr);
        t = 0;
        break;
      }
    }
  }
  if (t == 0) 
  {
    sen[s] = '\0';
    cout << "译码为:" << endl;
    cout << sen << endl;
  }
  else 
  {
    cout << "二进制源码有错!从第" << count + 1 << "位开始" << endl;
  }
}
int main()
{
  HuffmanTree HT;
  int b[100]={0};
  int i, j;
  int symbol = 1, x, k;
  cout << "请输入一段文字:";
  cin >> buff;
  int len = (int)strlen(buff);
  for (i = 0; i < len; i++)
  {
    for (j = 0; j < n; j++)
    {
      if (a[j] == buff[i])
      {
        b[j] = b[j] + 1;
        break;
      }
    }
    if (j >= n)
    {
      a[n] = buff[i];
      b[n] = 1;
      n++;
    }
  }
  cout << "字符和权值信息如下" << endl;
  for (i = 0; i < n; i++)
  {
    cout << "字符:" << a[i] << "  权值:" << b[i] << endl;
  }
  CreateHuffmanTree(HT, a, b);
  CreatHuffmanCode(HT);
  cout << "文字编码为:\n";
  for (int i = 0; i < len; i++)
  {
    for (int j = 0; j < n; j++)
    {
      if (buff[i] == HT[j].letter)
      {
        cout << HT[j].code;
        break;
      }
    }
  }
  cout << "\n译码:" << endl;
  while (1)
  {
    cout << "请输入要译码的二进制字符串,输入'#'结束:";
    x = 1;
    k = 0; 
    symbol = 1;
    while (symbol) 
    {
      cin >> p;
      if (p != '1' && p != '0' && p != '#') 
      {
        x = 0;
      }
      coding[k] = p;
      if (p == '#')
        symbol = 0;
      k++;
    }
    if (x == 1) 
    {
      HuffmanTreeDecode(HT, coding, k - 1);
    }
    else 
    {
      cout << "有非法字符!" << endl;
    }
    cout << "是否继续?(Y/N):";
    cin >> p;
    if (p == 'y' || p == 'Y')
      continue;
    else
      break;
  }
  return 0;
}

图的基本操作

实验内容

分别用邻接矩阵和邻接表对如下有向图实现:

1.输出存储结果;

2.计算各结点的出度和入度,并输出;

3.实现图的深度优先遍历和广度优先遍历,并输出。

代码实现

#include<stdio.h>
#include<stdlib.h>
#define MAXVEX 50
int visit[MAXVEX];
int in_deg[MAXVEX];//入度
int out_deg[MAXVEX];//出度 
typedef struct
{
  int vertices[MAXVEX];
  int arc[MAXVEX][MAXVEX];
  int vexnum, arcnum;
}MGraph;
typedef struct queue
{
  int* pBase;
  int front, rear;
}QUEUE;
void init_queue(QUEUE* Q)
{
  Q->pBase = (int*)malloc((sizeof(int)) * MAXVEX);
  Q->front = 0;
  Q->rear = 0;
}
bool isfull_queue(QUEUE* Q)
{
  if (((Q->rear + 1) % MAXVEX) == Q->front)
    return true;
  else
    return false;
}
bool isempty_queue(QUEUE* Q)
{
  if (Q->rear == Q->front)
    return true;
  else
    return false;
}
void in_queue(QUEUE* Q, int val)
{
  if (isfull_queue(Q))
    return;
  Q->pBase[Q->rear] = val;
  Q->rear = (Q->rear + 1) % MAXVEX;
}
int out_queue(QUEUE* Q)
{
  int temp = 0;
  if (isempty_queue(Q))
    return 0;
  temp = Q->pBase[Q->front];
  Q->front = (Q->front + 1) % MAXVEX;
  return temp;
}
void BFS(MGraph G, QUEUE* Q, int v)
{
  if (!visit[v]) {
    visit[v] = 1;
    printf("%d  ", G.vertices[v]);
    in_queue(Q, v);
  }
  while (!isempty_queue(Q)) {
    int temp = out_queue(Q);
    for (int i = 0; i < G.vexnum; i++) {
      if (G.arc[temp][i] != 0 && !visit[i]) {
        visit[i] = 1;
        printf("%d  ", G.vertices[i]);
        in_queue(Q, i);
      }
    }
  }
}
void BFST(MGraph G, QUEUE* Q)
{
  printf("\nBFS的遍历:");
  int i = 0;
  for (i = 0; i < G.arcnum; i++)
    visit[i] = 0;
  for (i = 0; i < G.vexnum; i++) {
    if (!visit[i])  BFS(G, Q, i);
  }
}
int LocateVex(MGraph G, int v)
{
  for (int i = 0; i < G.vexnum; i++) {
    if (G.vertices[i] == v)
      return i;
  }
  return 0;
}
void CreatMGraph(MGraph* G)
{
  int i = 0, j = 0;
  printf("请分别输入顶点数和边数: \n");
  scanf("%d%d", &(G->vexnum), &(G->arcnum));
  printf("请输入顶点信息:\n");
  for (i = 0; i < G->vexnum; i++)
    scanf("%d", &(G->vertices[i]));
  for (i = 0; i < G->vexnum; i++) {
    for (j = 0; j < G->vexnum; j++)
      G->arc[i][j] = 0;
  }
  printf("请输入构成边的两个顶点:  \n");
  for (i = 0; i < G->arcnum; i++) {
    int num, num1;
    scanf("%d%d", &num, &num1);
    int j = LocateVex(*G, num);
    int k = LocateVex(*G, num1);
    G->arc[j][k] = 1;
  }
}
void PrintMGraph(MGraph G)
{
  printf("*************************\n");
  printf("邻接矩阵的遍历:\n");
  for (int i = 0; i < G.vexnum; i++) {
    for (int j = 0; j < G.vexnum; j++) {
      printf("%d  ", G.arc[i][j]);
      if (G.arc[i][j] != 0)
        out_deg[i]++;
      if (G.arc[j][i] != 0)
        in_deg[i]++;
    }
    printf("\n");
  }
  printf("*************************\n");
}
void Print_in_out_deg(MGraph G)
{
  printf("\n*************************\n");
  printf("各顶点的度的遍历:\n");
  for (int i = 0; i < G.vexnum; i++) {
    printf("\n第%d条边的入度: %d 与出度: %d\n", i + 1, in_deg[i], out_deg[i]);
  }
  printf("*************************\n");
}
void DFS(MGraph G, int v)
{
  visit[v] = 1;
  printf("%d  ", G.vertices[v]);
  for (int i = 0; i < G.vexnum; i++) {
    if (G.arc[v][i] != 0 && visit[i] == 0)
      DFS(G, i);
  }
}
void DFST(MGraph G)
{
  printf("DFS的遍历:");
  for (int i = 0; i < G.vexnum; i++) {
    if (!visit[i])
      DFS(G, i);
  }
}
int main()
{
  MGraph G;
  QUEUE Q;
  init_queue(&Q);
  CreatMGraph(&G);
  PrintMGraph(G);
  DFST(G);
  BFST(G, &Q);
  Print_in_out_deg(G);
  return 0;
}


相关文章
|
存储 算法 编译器
数据结构实验之矩阵的运算器(二维数组)
本实验旨在通过团队合作,掌握数组和矩阵相关运算的代码实现,包括矩阵的加减、数乘、转置、乘法、n次方及行列式的计算。实验过程中,成员们需分工协作,解决编程难题,最终实现一个功能完备的矩阵计算器。通过本实验,不仅锻炼了编程能力,还加深了对数学概念的理解,同时培养了团队合作精神。
216 4
数据结构实验之串模式匹配问题
本实验旨在掌握串模式匹配技术,通过创建文本文件、实现单词计数与定位功能,最终构建一个包含文件建立、单词统计与定位、程序退出等选项的主菜单,以增强对字符串处理的理解与应用能力。
164 4
|
算法
数据结构实验之最长公共子序列
本实验旨在通过编程实践帮助学生理解串的基本概念及求解最长公共子序列的算法。实验内容包括使用动态规划方法设计并实现算法,以找出给定两序列的最大公共子序列。示例代码展示了如何通过构建状态矩阵和回溯路径来找到解决方案。实验总结指出,`memset()`函数用于内存初始化,且对于特定输入,程序能正确输出最长公共子序列之一。
208 4
|
算法
数据结构实验之操作系统打印机管理器问题
本实验旨在通过实现操作系统中的打印机管理器问题,掌握队列的基本操作如入队、出队等,利用队列的先进先出特性解决先申请先打印的问题。实验包括队列的初始化、入队、出队、打印队列内容等功能,并通过菜单式界面进行交互。实验结果显示基本功能可正常执行,但在连续操作时存在执行失败的情况,需进一步优化。
170 4
|
存储 算法 Perl
数据结构实验之链表
本实验旨在掌握线性表中元素的前驱、后续概念及链表的建立、插入、删除等算法,并分析时间复杂度,理解链表特点。实验内容包括循环链表应用(约瑟夫回环问题)、删除单链表中重复节点及双向循环链表的设计与实现。通过编程实践,加深对链表数据结构的理解和应用能力。
220 4
|
搜索推荐 C语言
【排序算法】快速排序升级版--三路快排详解 + 实现(c语言)
本文介绍了快速排序的升级版——三路快排。传统快速排序在处理大量相同元素时效率较低,而三路快排通过将数组分为三部分(小于、等于、大于基准值)来优化这一问题。文章详细讲解了三路快排的实现步骤,并提供了完整的代码示例。
401 4
|
10月前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
348 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
12月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
413 1
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
245 4
|
机器学习/深度学习 存储 算法
数据结构实验之二叉树实验基础
本实验旨在掌握二叉树的基本特性和遍历算法,包括先序、中序、后序的递归与非递归遍历方法。通过编程实践,加深对二叉树结构的理解,学习如何计算二叉树的深度、叶子节点数等属性。实验内容涉及创建二叉树、实现各种遍历算法及求解特定节点数量。
308 4
下一篇
oss云网关配置