当前位置: 首页 > news >正文

数据结构与算法教程,数据结构C语言版教程!(第四部分、字符串,数据结构中的串存储结构)二

第四部分、字符串,数据结构中的串存储结构

串存储结构,也就是存储字符串的数据结构。

很明显,字符串之间的逻辑关系也是“一对一”,用线性表的思维不难想出,串存储结构也有顺序存储和链式存储。

提到字符串,常做的操作就是串之间的匹配,因为,本章给初学者介绍 2 种串的模式匹配算法,BF 算法和 KMP 算法。

三、串的堆分配存储结构

串的堆分配存储其具体实现方式是采用动态数组存储字符串。

通常,编程语言会将程序占有的内存空间分成多个不同的区域,程序包含的数据会被分门别类并存储到对应的区域。拿 C 语言来说,程序会将内存分为 4 个区域,分别为堆区、栈区、数据区和代码区,其中的堆区是本节所关注的。

与其他区域不同,堆区的内存空间需要程序员手动使用 malloc 函数申请,并且在不用后要手动通过 free 函数将其释放。

C 语言中使用 malloc 函数最多的场景是给数组分配空间,这类数组称为动态数组例如:

char * a = (char*)malloc(5*sizeof(char));

此行代码创建了一个动态数组 a,通过使用 malloc 申请了 5 个 char 类型大小的堆存储空间。

动态数组相比普通数组(静态数组)的优势是长度可变,换句话说,根据需要动态数组可额外申请更多的堆空间(使用 relloc 函数):

a = (char*)realloc(a, 10*sizeof(char));

通过使用这行代码,之前具有 5 个 char 型存储空间的动态数组,其容量扩大为可存储 10 个 char 型数据。

下面给大家举一个完整的示例,以便对串的堆分配存储有更清楚地认识。该程序可实现将两个串("data.bian" 和 "cheng.net")合并为一个串:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

int main()

{

        char * a1 = NULL;

        char * a2 = NULL;

        a1 = (char*)malloc(10 * sizeof(char));

        strcpy(a1, "data.bian");//将字符串"data.bian"复制给a1

        a2 = (char*)malloc(10 * sizeof(char));

        strcpy(a2, "cheng.net");

        int lengthA1 = strlen(a1);//a1串的长度

        int lengthA2 = strlen(a2);//a2串的长度

        //尝试将合并的串存储在 a1 中,如果 a1 空间不够,则用realloc动态申请

        if (lengthA1 < lengthA1 + lengthA2) {

                a1 = (char*)realloc(a1, (lengthA1 + lengthA2+1) * sizeof(char));

        }

        //合并两个串到 a1 中

        for (int i = lengthA1; i < lengthA1 + lengthA2; i++) {

                a1[i] = a2[i - lengthA1];

        }

        //串的末尾要添加 \0,避免出错

        a1[lengthA1 + lengthA2] = '\0';

        printf("%s", a1);

        //用完动态数组要立即释放

        free(a1);

        free(a2);

        return 0;

}

程序运行结果:

data.biancheng.net

注意,程序中给 a1 和 a2 赋值时,使用了 strcpy 复制函数。这里不能直接用 a1 ="data.biancheng",程序编译会出错,报错信息为 "没有 malloc 的空间不能 free"。因为 strcpy 函数是将字符串复制到申请的存储空间中,而直接赋值是字符串存储在别的内存空间(本身是一个常量,放在数据区)中,更改了指针 a1 和 a2 的指向,也就是说,之前动态申请的存储空间虽然申请了,结果还没用呢就丢了。


四、串的块链存储结构

串的块链存储,指的是使用链表结构存储字符串。

本节实现串的块链存储使用的是无头节点的单链表。当然根据实际需要,你也可以自行决定所用链表的结构(双链表还是单链表,有无头节点)。

我们知道,单链表中的 "单" 强调的仅仅是链表各个节点只能有一个指针,并没有限制数据域中存储数据的具体个数。因此在设计链表节点的结构时,可以令各节点存储多个数据。

例如,图 1 所示是用链表存储字符串 shujujiegou,该链表各个节点中可存储 1 个字符:

各节点仅存储 1 个数据元素的链表

图 1 各节点仅存储 1 个数据元素的链表

同样,图 2 设置的链表各节点可存储 4 个字符:

各节点可存储 4 个数据元素的链表

图 2 各节点可存储 4 个数据元素的链表

从图 2 可以看到,使用链表存储字符串,其最后一个节点的数据域不一定会被字符串全部占满,对于这种情况,通常会用 '#' 或其他特殊字符(能与字符串区分开就行)将最后一个节点填满。

初学者可能会问,使用块链结构存储字符串时,怎样确定链表中节点存储数据的个数呢?

链表各节点存储数据个数的多少可参考以下几个因素:

  1. 串的长度和存储空间的大小:若串包含数据量很大,且链表申请的存储空间有限,此时应尽可能的让各节点存储更多的数据,提高空间的利用率(每多一个节点,就要多申请一个指针域的空间);反之,如果串不是特别长,或者存储空间足够,就需要再结合其他因素综合考虑;
  2. 程序实现的功能:如果实际场景中需要对存储的串做大量的插入或删除操作,则应尽可能减少各节点存储数据的数量;反之,就需要再结合其他因素。

以上两点仅是目前想到影响节点存储数据个数的因素,在实际场景中,还需结合实现环境综合分析。

这里给出一个实现串的块链存储的 C 语言程序,以加深初学者对此字符串存储方式的认识:

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#define linkNum 3//全局设置链表中节点存储数据的个数

typedef struct Link {

        char a[linkNum]; //数据域可存放 linkNum 个数据

        struct Link * next; //代表指针域,指向直接后继元素

}link; // nk为节点名,每个节点都是一个 link 结构体

link * initLink(link * head, char * str);

void displayLink(link * head);

int main()

{

        link * head = NULL;

        head = initLink(head, "data.biancheng.net");

        displayLink(head);

        return 0;

}

//初始化链表,其中head为头指针,str为存储的字符串

link * initLink(link * head, char * str) {

        int length = strlen(str);

        //根据字符串的长度,计算出链表中使用节点的个数

        int num = length/linkNum;

        if (length%linkNum) {

                num++;

        }

        //创建并初始化首元节点

        head = (link*)malloc(sizeof(link));

        head->next = NULL;

        link *temp = head;

        //初始化链表

        for (int i = 0; i<num; i++)

        {

                int j = 0;

                for (; j<linkNum; j++)

                {

                        if (i*linkNum + j < length) {

                                temp->a[j] = str[i*linkNum + j];

                        }

                        else

                                temp->a[j] = '#';

                }

                if (i*linkNum + j < length)

                {

                        link * newlink = (link*)malloc(sizeof(link));

                        newlink->next = NULL;

                        temp->next = newlink;

                        temp = newlink;

                }

        }

        return head;

}

//输出链表

void displayLink(link * head) {

        link * temp = head;

        while (temp) {

                for (int i = 0; i < linkNum; i++) {

                        printf("%c", temp->a[i]);

                }

                temp = temp->next;

        }

}

程序输出结果为:

data.biancheng.net

相关文章:

数据结构与算法教程,数据结构C语言版教程!(第四部分、字符串,数据结构中的串存储结构)二

第四部分、字符串&#xff0c;数据结构中的串存储结构 串存储结构&#xff0c;也就是存储字符串的数据结构。 很明显&#xff0c;字符串之间的逻辑关系也是“一对一”&#xff0c;用线性表的思维不难想出&#xff0c;串存储结构也有顺序存储和链式存储。 提到字符串&#xff…...

第七在线荣获百灵奖 Buylink Awards 2023零售圈年度卓越服务商品牌

1月11日&#xff0c;由零售圈主办、20零售连锁协会协办、30零售行业媒体支持的中国零售圈大会暨2024未来零售跨年盛典在西安落下帷幕&#xff0c;在这个零售行业盛典中&#xff0c;第七在线凭借其高精尖产品和卓越的服务质量成功入选&#xff0c;并荣获了“百灵奖 Buylink Awar…...

通过myBatis将sql语句返回的值自动包装成一个java对象(3)

1.如果sql字段和java字段名字不一样怎么办&#xff1f; 之前我们将sql返回值转换为java对象时&#xff0c;每条sql的返回值的字段名和java类中的字段名是一一对应的&#xff0c;ie&#xff1a;sql选择的user有username和password两个字段&#xff0c;java中的user对象也有两个…...

基于SSM的驾校信息管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue、HTML 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是…...

矩阵行列式的四大应用

目录 一. 介绍 二. 行列式的基本性质 2.1 单位阵的行列式 2.2 交换行位置的行列式 三. 矩阵求逆与行列式 四. 体积与行列式 五. 矩阵主元与行列式 六. 解方程与矩阵行列式 七. 小结 一. 介绍 行列式可以反应矩阵的很多性质&#xff0c;比如可以求矩阵的逆&#xff0c…...

【小笔记】时序数据分类算法最新小结

2024.1.15 最近基于时序数据训练分类算法&#xff0c;对其进行了一番了解&#xff0c;主要围绕以下几点&#xff1a; 时序数据算法有哪些细分类&#xff1f;时序数据分类算法经典模型&#xff1f;当下时序分类算法模型强baseline&#xff1f;有没有现成的工具&#xff1f; 1…...

使用Python+pygame实现贪吃蛇小游戏

使用Pythonpygame贪吃蛇小游戏 使用第三方库pygame&#xff0c;关于Python中pygame游戏模块的安装使用可见 https://blog.csdn.net/cnds123/article/details/119514520 给出两种实现。 第一种 运行效果如下&#xff1a; 游戏源码如下&#xff1a; import pygame import sy…...

SpringBoot 全局异常统一处理:BindException(绑定异常)

概述 在Spring Boot应用中&#xff0c;数据绑定是一个至关重要的环节&#xff0c;它负责将HTTP请求中的参数映射到控制器方法的入参对象上。在这个过程中如果遇到任何问题&#xff0c;如参数缺失、类型不匹配或验证失败等&#xff0c;Spring MVC将会抛出一个org.springframewo…...

ucloud轻量云(wordpress)配置ssl

ucloud 轻量云(wordpress)配置ssl 1、上传ssl证书到/usr/local/software/apache/conf&#xff0c;这里的文件名和内容与ucloud控制台下载下来的文件名和内容保持一致 2、修改httpd.conf文件 vim /usr/local/software/apache/conf/httpd.conf 找到下面两行&#xff0c;去掉注…...

电脑/设备网络共享给其他设备上网

文章目录 一、概述二、设置网络共享2.1 电脑可以上网&#xff0c;通过网络共享让其他设备也可以上网2.2 手机如何使用USB数据线共享网络给电脑 一、概述 现在有如下几种情况&#xff1a; 设备本身不能上网&#xff0c;需要通过电脑上网 笔记本WIFI连热点上网&#xff0c;然后…...

vue之虚拟滚动

一、解决的问题 对于大量数据的懒加载&#xff0c;我们可以使用虚拟滚动的技术。虚拟滚动的原理是只渲染可视区域内的数据&#xff0c;当用户滚动时&#xff0c;动态计算并渲染新的可视数据&#xff0c;从而实现大数据量的流畅滚动。 在Vue中&#xff0c;我们可以使用第三方库…...

Redis学习指南(11)-Redis的有序集合数据类型介绍

文章目录 特点和用途常用命令插入操作查询操作删除操作 示例总结 Redis的有序集合数据类型是一种高效的数据结构&#xff0c;能够存储多个成员和对应的分值&#xff0c;并能够根据分值进行快速的查找、插入和删除操作。本文将详细介绍Redis的有序集合数据类型&#xff0c;包括其…...

Spring的纯注解配置

1.环境搭建 1.1.创建工程 1.2.待改造的问题 我们发现&#xff0c;之所以我们现在离不开xml配置文件&#xff0c;是因为我们有一处很关键的配置&#xff0c;如果他要也能用注解配置&#xff0c;那么我们就可以脱离xml文件了&#xff1a; 1.2.1.jdbc配置 <context:propert…...

numpy 筛选多段数据

目录 掩码方式 利用切片 掩码方式 range_to_remove list(range(77-1, 111-1)) list(range(122-1, 135-1))keep_mask np.ones(image0_cut.shape[0], dtypebool)keep_mask[range_to_remove] Falseprocessed_data image0_cut[keep_mask] 利用切片 import numpy as np# 假设…...

【Kotlin】协程的字节码原理

前言 协程是Koltin语言最重要的特性之一&#xff0c;也是最难理解的特性。网上关于kotlin协程的描述也是五花八门&#xff0c;有人说它是轻量级线程&#xff0c;有人说它是无阻塞式挂起&#xff0c;有人说它是一个异步框架等等&#xff0c;众说纷芸。甚至还有人出了书籍专门介…...

区间预测 | Matlab实现LSSVM-ABKDE的最小二乘支持向量机结合自适应带宽核密度估计多变量回归区间预测

区间预测 | Matlab实现LSSVM-ABKDE的最小二乘支持向量机结合自适应带宽核密度估计多变量回归区间预测 目录 区间预测 | Matlab实现LSSVM-ABKDE的最小二乘支持向量机结合自适应带宽核密度估计多变量回归区间预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现…...

基于深度学习的实例分割的Web应用

基于深度学习的实例分割的Web应用 1. 项目简介1.1 模型部署1.2 Web应用 2. Web前端开发3. Web后端开发4. 总结 1. 项目简介 这是一个基于深度学习的实例分割Web应用的项目介绍。该项目使用PaddlePaddle框架&#xff0c;并以PaddleSeg训练的图像分割模型为例。 1.1 模型部署 …...

20240115如何在线识别俄语字幕?

20240115如何在线识别俄语字幕&#xff1f; 2024/1/15 21:25 百度搜索&#xff1a;俄罗斯语 音频 在线识别 字幕 Bilibili&#xff1a;俄语AI字幕识别 音视频转文字 字幕小工具V1.2 BING&#xff1a;音视频转文字 字幕小工具V1.2 https://www.bilibili.com/video/BV1d34y1F7…...

Flink 处理函数(1)—— 基本处理函数

在 Flink 的多层 API中&#xff0c;处理函数是最底层的API&#xff0c;是所有转换算子的一个概括性的表达&#xff0c;可以自定义处理逻辑 在处理函数中&#xff0c;我们直面的就是数据流中最基本的元素&#xff1a;数据事件&#xff08;event&#xff09;、状态&#xff08;st…...

Linux系统下编译MPlayer

一、编译MPlayer 在 http://www.mplayerhq.hu/design7/dload.html 下载MPlayer源码 执行命令&#xff1a; tar -xf MPlayer-1.5.tar.xz cd MPlayer-1.5 ./configure --prefix$(pwd)/install --yasm make make install 然后在install/bin目录下即会生成mplayer的可执行文件 二…...

无缝跨平台体验:APK-Installer让Windows运行Android应用的革命性工具

无缝跨平台体验&#xff1a;APK-Installer让Windows运行Android应用的革命性工具 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 在数字化时代&#xff0c;用户常常面临…...

偏迹(Partial Trace)的定义和数学物理意义

我们将通过多个计算示例来掌握偏迹&#xff08;Partial Trace&#xff09;。1. 偏迹的定义1.1 动机在量子力学中&#xff0c;复合系统 的态用密度矩阵 ​ 描述。那么&#xff0c;当我们只关心子系统 时&#xff0c;需要忽略掉其中 的状态&#xff0c;这里通过对子系统 求平…...

nba篮球数据项目书

import pandas as pd import randomdef get_2000_nba_players():"""生成2000条NBA球员数据&#xff08;基于真实球员名 合理数据&#xff09;100%成功&#xff0c;无需网络请求"""# 真实NBA球员名&#xff08;前200名真实球员&#xff09;real_…...

**发散创新:基于Python的轻量级知识推理引擎实现与实战**在人工智能飞速发展的今天,**知识推理**

发散创新&#xff1a;基于Python的轻量级知识推理引擎实现与实战 在人工智能飞速发展的今天&#xff0c;知识推理已成为构建智能系统的核心能力之一。它不仅支撑着推荐系统、问答机器人和语义搜索等场景&#xff0c;更是实现AI从“感知”向“理解”跃迁的关键路径。本文将带你…...

欧洲发布Euro-Office引发OnlyOffice强烈抗议

欧洲企业Ionos和Nextcloud联合推出了Euro-Office&#xff0c;这是基于OnlyOffice云办公套件的分支版本&#xff0c;专为对数字主权有顾虑的组织而设计&#xff0c;此举引发了原开发商的愤怒回应。几天前&#xff0c;以德国自托管云服务商Nextcloud为首的"欧洲企业和社区组…...

考研408计算机学科专业基础——计算机组成原理复习

考研408计算机学科专业基础——计算机组成原理复习 核心说明&#xff1a;本笔记聚焦考研408计算机组成原理&#xff08;计组&#xff09;高频考点、必背知识点&#xff0c;贴合命题规律&#xff08;选择大题&#xff09;&#xff0c;剔除冗余内容&#xff0c;突出重难点&#x…...

Unity/Godot开发者看过来:手把手教你将Spine动画导出并集成到游戏引擎里(附常见报错解决)

Unity/Godot开发者实战指南&#xff1a;Spine动画工程化集成全流程解析 当你在Spine中完成了一个令人满意的角色动画后&#xff0c;接下来面临的真正挑战是如何让它活灵活现地跑在游戏引擎里。作为经历过无数次Spine动画集成的老手&#xff0c;我深知这个过程中可能遇到的种种…...

告别手动压缩!用Python的shutil.make_archive()自动备份你的项目文件

告别手动压缩&#xff01;用Python的shutil.make_archive()自动备份你的项目文件 深夜赶项目时&#xff0c;你是否经历过这样的崩溃瞬间——修改了三天的重要代码突然消失&#xff0c;而上次备份还是一周前的手动压缩包&#xff1f;作为开发者&#xff0c;我们常陷入"明天…...

破解土地-生态耦合难题,从数据处理到SCI论文:AI辅助下PLUS-InVEST模型土地利用格局模拟与生态系统服务

做土地利用、生态系统服务、国土空间规划的同学&#xff0c;是不是经常遇到这些问题&#xff1a;PLUS 模型装不上、跑不通、参数看不懂InVEST 产水 / 土壤保持 / 碳储量 / 生境质量数据总是报错ArcGIS 栅格处理、投影转换、重分类一头雾水多情景模拟不会设计&#xff0c;结果不…...

深入解析:成为一名卓越的 Android 开发工程师

引言 在移动互联网蓬勃发展的今天,Android 系统凭借其开放性和庞大的用户基数,在全球范围内占据着主导地位。Android 开发工程师作为构建移动应用体验的核心力量,其角色日益重要。本文旨在深入探讨成为一名优秀的 Android 开发工程师所需的核心技能、职责要求以及面对的技术…...