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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/59969.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Zebec Payroll :计划推2出 WageLink On-Demand Pay,进军薪酬发放领域

“Zebec Protocol生态旨以Web3的方式建立全新的公平秩序&#xff0c;基于其流支付体系构建的薪酬支付板块&#xff0c;就是解决问题的一把利刃” Zebec Protocol在创立之初就有着一个十分宏大的愿景&#xff0c;其希望通过Web3的方式来进一步打破世界上一些不公平现象。 Zebec …

【漏洞复现】Metabase 远程命令执行漏洞(CVE-2023-38646)

文章目录 前言声明一、漏洞介绍二、影响版本三、漏洞原理四、漏洞复现五、修复建议 前言 Metabase 0.46.6.1之前版本和Metabase Enterprise 1.46.6.1之前版本存在安全漏洞&#xff0c;未经身份认证的远程攻击者利用该漏洞可以在服务器上以运行 Metabase 服务器的权限执行任意命…

docker配置远程连接端口

配置docker 配置远程连接端口 vi /lib/systemd/system/docker.servicesystemctl daemon-reload && systemctl restart docker firewall-cmd --zonepublic --add-port2375/tcp --permanenthttp://node2:2375/version

Leetcode.931 下降路径最小和

题目链接 Leetcode.931 下降路径最小和 rating : 1573 题目描述 给你一个 n x n 的 方形 整数数组 m a t r i x matrix matrix &#xff0c;请你找出并返回通过 m a t r i x matrix matrix 的下降路径 的 最小和 。 下降路径 可以从第一行中的任何元素开始&#xff0c;并从…

机器学习基础知识(1)

什么是机器学习 机器学习是一种通过输入大量数据来构建一种模型&#xff08;网络&#xff09;&#xff0c;这个训练好的模型将会被用来预测或执行某些操作&#xff0c;这个训练的过程和方法就是机器学习。 我们也可以理解为构建一个“函数”&#xff0c;使得这个函数面对我们…

如何维护你的电脑:打造IT人的重要武器

文章目录 方向一&#xff1a;介绍我的电脑方向二&#xff1a;介绍我的日常维护措施1. 定期清理和优化2. 保持良好的上网习惯和安全防护3. 合理安排软件和硬件的使用4. 数据备份和系统还原 方向三&#xff1a;推荐的维护技巧1. 数据分区和多系统安装2. 内部清洁和散热优化3. 安全…

Html页面连线工具

在项目中遇了一个需要连线配置的功能。该功能引用了 bootstrap、layui 、svg-line等插件 下载链接 lixhttps://download.csdn.net/download/dongyan3595/88168121

docker 部署mysql 5.6集群

docker搭建mysql的集群&#xff08;一主双从&#xff09; 1.拉取镜像 docker pull mysql:5.6 2.启动master容器 docker run -it -d --name mysql_master -p 3306:3306 --ip 192.168.162.100 \ -v /data/mysql_master/mysql:/var/lib/mysql \ -v /data/mysql_master/conf.d…

【C++基础(六)】类和对象(中) --拷贝构造,运算符重载

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C初阶之路⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; 类和对象 1. 前言2. 拷贝构造函数2.1 对拷贝构造函数…

5G网络在中国已经普及了,政策支持加大5G投入力度,这意味着什么呢?

5G网络是新型基础设施的重要组成部分&#xff0c;中国5G商用牌照已发放四年多&#xff0c;目前发展得怎样了&#xff1f;最近&#xff0c;官方公布了最新数据&#xff0c;截至7月底&#xff0c;中国5G移动电话用户已达7亿户&#xff0c;5G基站累计达到293.7万个&#xff0c;5G覆…

HDFS介绍

目录 ​编辑 一、HDFS基础 1.1 概述 1.2 HDFS的设计目标 1.2.1 硬件故障 1.2.2 流式数据访问 1.2.3 超大数据集 1.2.4 简单的一致性模型 1.2.5 移动计算而不是移动数据 1.2.6 跨异构硬件和软件平台的可移植性 1.3 基础概念 1.3.1 块&#xff08;Block&#xff09; 1.3.2 复制…

Nodejs 第四章(Npm install 原理)

在执行npm install 的时候发生了什么&#xff1f; 首先安装的依赖都会存放在根目录的node_modules,默认采用扁平化的方式安装&#xff0c;并且排序规则.bin第一个然后系列&#xff0c;再然后按照首字母排序abcd等&#xff0c;并且使用的算法是广度优先遍历&#xff0c;在遍历依…

STM32F0实现IAP升级固件

好几年前写过一篇关于 STM32 bootloader 升级固件的博客&#xff0c;但是使用的芯片是 STM32 F4 系列&#xff0c;升级固件的方式是在外部 flash 的 fat32 文件系统中存入固件文件&#xff0c;reset 后通过特定按键进入 IAP 程序。 最近需要在 STM32 上实现同样的 IAP 功能&am…

过程:从虚拟机上添加 git 并成功提交到 GitLab 的全过程

Ⅰ、准备工作&#xff1a; 1、Git 查看&#xff1a; 其一、命令&#xff1a;git --version // 此时就能在虚拟机环境下看到 git 的版本为: git version 2.41.0 其二、如何在虚拟机上安装 git &#xff1a; A、命令 &#xff1a; sudo apt-get install git B、然后再输入虚…

HDFS的QJM方案

Quorum Journal Manager仲裁日志管理器 介绍主备切换&#xff0c;脑裂问题解决---ZKFailoverController&#xff08;zkfc&#xff09;主备切换&#xff0c;脑裂问题解决-- Fencing&#xff08;隔离&#xff09;机制主备数据状态同步问题解决 HA集群搭建集群基础环境准备HA集群规…

宋浩概率论笔记(三)随机向量/二维随机变量

第三更&#xff1a;本章的内容最重要的在于概念的理解与抽象&#xff0c;二重积分通常情况下不会考得很难。此外&#xff0c;本次暂且忽略【二维连续型随机变量函数的分布】这一章节&#xff0c;非常抽象且难度较高&#xff0c;之后有时间再更新。

C++ 深拷贝和浅拷贝

虽然我们知道了拷贝构造函数&#xff0c;但是大多数简单程序中都不需要特别编写拷贝构造函数&#xff0c;隐含的拷贝构造函数足以实现对象间数据元素的一一对应复制。但是隐含的拷贝构造函数并不总是适用的&#xff0c;因为它完成的只是浅拷贝。 1.浅拷贝 【例】对象的浅拷贝…

面试热题(打家窃舍)

一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响小偷偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定一个代表每个房屋存放金额的非负…

通话降噪算法在手机和IOT设备上的应用和挑战

随着电子产品的升级换代&#xff0c;用户对通话质量的要求也越来越高。通话降噪算法对通话质量起到了关键核心的作用。计算资源的提升使得深度学习模型在便携式的低功耗芯片上面跑起来了&#xff0c;器件成本降低让IoT设备开始使用骨导传感器&#xff0c;&#xff0c;那怎么样才…

Python接口自动化-requests模块之post请求

一、源码解析 def post(url, dataNone, jsonNone, **kwargs):r"""Sends a POST request.:param url: URL for the new :class:Request object.:param data: (optional) Dictionary, list of tuples, bytes, or file-likeobject to send in the body of the :cla…