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;
}


相关文章
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
785 1
|
存储 算法 编译器
数据结构实验之矩阵的运算器(二维数组)
本实验旨在通过团队合作,掌握数组和矩阵相关运算的代码实现,包括矩阵的加减、数乘、转置、乘法、n次方及行列式的计算。实验过程中,成员们需分工协作,解决编程难题,最终实现一个功能完备的矩阵计算器。通过本实验,不仅锻炼了编程能力,还加深了对数学概念的理解,同时培养了团队合作精神。
394 4
数据结构实验之串模式匹配问题
本实验旨在掌握串模式匹配技术,通过创建文本文件、实现单词计数与定位功能,最终构建一个包含文件建立、单词统计与定位、程序退出等选项的主菜单,以增强对字符串处理的理解与应用能力。
239 4
|
算法
数据结构实验之最长公共子序列
本实验旨在通过编程实践帮助学生理解串的基本概念及求解最长公共子序列的算法。实验内容包括使用动态规划方法设计并实现算法,以找出给定两序列的最大公共子序列。示例代码展示了如何通过构建状态矩阵和回溯路径来找到解决方案。实验总结指出,`memset()`函数用于内存初始化,且对于特定输入,程序能正确输出最长公共子序列之一。
323 4
|
算法
数据结构实验之操作系统打印机管理器问题
本实验旨在通过实现操作系统中的打印机管理器问题,掌握队列的基本操作如入队、出队等,利用队列的先进先出特性解决先申请先打印的问题。实验包括队列的初始化、入队、出队、打印队列内容等功能,并通过菜单式界面进行交互。实验结果显示基本功能可正常执行,但在连续操作时存在执行失败的情况,需进一步优化。
243 4
|
存储 算法 Perl
数据结构实验之链表
本实验旨在掌握线性表中元素的前驱、后续概念及链表的建立、插入、删除等算法,并分析时间复杂度,理解链表特点。实验内容包括循环链表应用(约瑟夫回环问题)、删除单链表中重复节点及双向循环链表的设计与实现。通过编程实践,加深对链表数据结构的理解和应用能力。
341 4
|
11月前
|
存储 监控 安全
企业上网监控系统中红黑树数据结构的 Python 算法实现与应用研究
企业上网监控系统需高效处理海量数据,传统数据结构存在性能瓶颈。红黑树通过自平衡机制,确保查找、插入、删除操作的时间复杂度稳定在 O(log n),适用于网络记录存储、设备信息维护及安全事件排序等场景。本文分析红黑树的理论基础、应用场景及 Python 实现,并探讨其在企业监控系统中的实践价值,提升系统性能与稳定性。
694 1
|
存储 算法 搜索推荐
Python 中数据结构和算法的关系
数据结构是算法的载体,算法是对数据结构的操作和运用。它们共同构成了计算机程序的核心,对于提高程序的质量和性能具有至关重要的作用
567 153
|
11月前
|
存储 监控 算法
基于跳表数据结构的企业局域网监控异常连接实时检测 C++ 算法研究
跳表(Skip List)是一种基于概率的数据结构,适用于企业局域网监控中海量连接记录的高效处理。其通过多层索引机制实现快速查找、插入和删除操作,时间复杂度为 $O(\log n)$,优于链表和平衡树。跳表在异常连接识别、黑名单管理和历史记录溯源等场景中表现出色,具备实现简单、支持范围查询等优势,是企业网络监控中动态数据管理的理想选择。
277 0
|
存储 机器学习/深度学习 算法
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
583 30