数据结构(4.1)——串的存储结构

串的顺序存储

串(String)的顺序存储是指使用一段连续的存储单元来存储字符串中的字符。

计算串的长度

静态存储(定长顺序存储)

#define MAXLEN 255//预定义最大串为255typedef struct {char ch[MAXLEN];//每个分量存储一个字符int length;//串的实际长度
}SString;

动态存储(堆分配存储)

typedef struct {char* ch;//按串长分配存储区,ch指向串的基地址int length;//串的长度
}HString;
void main() {HString S;S.ch = (char*)malloc(MAXLEN * sizeof(char));S.length = 0;
}

注意调用完malloc函数后需要手动用free函数回收内存空间

代码示例

#include <stdio.h>
#include <stdlib.h>#define MAXLEN 100 // 定义串的最大长度typedef struct {char ch[MAXLEN];      // 按串长分配存储区int length;    // 串的长度
} HString;// 函数:initString
// 功能:初始化一个HString串
// 参数:str - 指向HString结构的指针
void initString(HString *str) {str->length = 0;
}// 函数:assignString
// 功能:为HString串赋值
// 参数:str - 指向HString结构的指针
//       chars - 要赋值的字符数组
void assignString(HString *str, char *chars) {int i = 0;while (chars[i] != '\0' && i < MAXLEN) {str->ch[i] = chars[i];i++;}str->length = i;
}// 函数:concatString
// 功能:连接两个HString串
// 参数:str1 - 第一个HString串
//       str2 - 第二个HString串
// 返回值:连接后的HString串
HString concatString(HString str1, HString str2) {HString result;initString(&result);int i, j;for (i = 0; i < str1.length; i++) {result.ch[i] = str1.ch[i];}for (j = 0; j < str2.length && i + j < MAXLEN; j++) {result.ch[i + j] = str2.ch[j];}result.length = i + j;return result;
}// 函数:printString
// 功能:打印一个HString串
// 参数:str - 要打印的HString串
void printString(HString str) {for (int i = 0; i < str.length; i++) {printf("%c", str.ch[i]);}printf("\n");
}int main() {HString S, T, R;// 初始化串initString(&S);initString(&T);// 赋值assignString(&S, "Hello");assignString(&T, " World");// 打印原始串printString(S);printString(T);// 连接两个串R = concatString(S, T);printString(R);return 0;
}

串的链式存储

串的链式存储结构是指使用链表来存储字符串中的字符。

typedef struct {char ch;//每个结点存1个字符struct StringNode* next;
}StringNode, * String;

但这样子的操作会造成内存存储密度过低 

所以我们可以优化一下代码,在每个结点多存一些字符

typedef struct {char ch[4];//每个结点存多个字符struct StringNode* next;
}StringNode, * String;

代码示例 

#include <stdio.h>
#include <stdlib.h>typedef struct Node {char data;          // 存储字符数据struct Node* next;  // 指向下一个节点的指针
} Node;typedef struct {Node* head;         // 指向链表头节点的指针int length;         // 串的长度
} LString;// 函数:initLString
// 功能:初始化一个LString串
// 参数:str - 指向LString结构的指针
void initLString(LString *str) {str->head = NULL;str->length = 0;
}// 函数:appendLString
// 功能:向LString串追加一个字符
// 参数:str - 指向LString结构的指针
//       ch - 要追加的字符
void appendLString(LString *str, char ch) {Node* newNode = (Node*)malloc(sizeof(Node));if (newNode == NULL) {printf("内存分配失败\n");exit(1);}newNode->data = ch;newNode->next = NULL;if (str->head == NULL) {// 如果链表为空,新节点作为头节点str->head = newNode;} else {// 否则,找到链表的最后一个节点,并追加新节点Node* current = str->head;while (current->next != NULL) {current = current->next;}current->next = newNode;}str->length++;
}// 函数:printLString
// 功能:打印一个LString串
// 参数:str - 要打印的LString串
void printLString(LString str) {Node* current = str.head;while (current != NULL) {printf("%c", current->data);current = current->next;}printf("\n");
}// 函数:freeLString
// 功能:释放LString串的内存
// 参数:str - 指向LString结构的指针
void freeLString(LString *str) {Node* current = str->head;while (current != NULL) {Node* temp = current;current = current->next;free(temp);}str->head = NULL;str->length = 0;
}int main() {LString S;// 初始化串initLString(&S);// 追加字符appendLString(&S, 'H');appendLString(&S, 'e');appendLString(&S, 'l');appendLString(&S, 'l');appendLString(&S, 'o');// 打印串printLString(S);// 释放内存freeLString(&S);return 0;
}

 基本操作的实现

求子串

SubString(&Sub,S,pos,len):求子串。用Sub返回串S的第pos个字符起长度为len的子串

// 函数SubString:从字符串S中提取从pos位置开始的长度为len的子串
bool SubString(SString *Sub, SString S, int pos, int len) {if (pos + len - 1 > S.length || pos < 1) // 检查子串范围是否越界return false; // 如果越界,返回falsefor (int i = pos; i < pos + len; i++) // 循环,将子串复制到Sub中//将源字符串S中从pos开始的第i个字符复制到目标子串Sub的相应位置Sub->ch[i - pos + 1] = S.ch[i];Sub->ch[len] = '\0'; // 在子串末尾添加空字符,标记字符串结束Sub->length = len;   // 设置子串的长度return true;         // 如果操作成功,返回true
}

比较操作

StrCompare(S,T):比较操作。若S>T,则返回值>0:若S=T,则返回值<0;

//比较操作。若S>T,则返回值>0:若S=T,则返回值<0;
int StrCompare(SString S, SString T) {for (int i = 1; i <= S.length && i <= T.length; i++) {if (S.ch[i] != T.ch[i])return S.ch[i] - T.ch[i];}//扫描过的所有字符都相同,则长度长的串更大return S.length - T.length;
}

定位操作

Index(S,T):定位操作。若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置;否则函数值为0

// 函数Index:在主串S中查找子串T的位置
// 返回值:如果找到子串,返回子串在主串中的位置(从1开始计数)
//         如果没有找到,返回0
int Index(SString S, SString T) {int i = 1, n = StrLength(S), m = StrLength(T);SString sub; // 定义一个SString变量,用于暂存从主串S中提取的子串// 循环,直到i超过可能存在子串的最后一个位置while (i <= n - m + 1) {SubString(&sub, S, i, m); // 从S中提取从位置i开始的长度为m的子串if (StrCompare(sub, T) != 0) // 如果提取的子串与T不相等++i; // 移动到下一个位置elsereturn i; // 如果找到相等的子串,返回其在主串中的位置}return 0; // 如果循环结束还没有找到子串,返回0
}

 总结:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

子进程继承父进程文件描述符导致父进程打开设备文件失败

开发过程中有时会遇到需要在程序中执行三方程序或者shell脚本&#xff0c;一般会通过system(), popen(), exec簇来完成该功能。我们知道以上方法会通过fork创建子进程后在子进程中执行相应指令。如图1为某个示例流程&#xff0c;具体的程序执行流程如图2所示&#xff0c;线程my…

计算机图形学入门28:相机、透镜和光场

1.前言 相机(Cameras)、透镜(Lenses)和光场(Light Fields)都是图形学中重要的组成部分。在之前的学习中&#xff0c;都是默认它们的存在&#xff0c;所以现在也需要单独拿出来学习下。 2.成像方法 计算机图形学有两种成像方法&#xff0c;即合成(Synthesis)和捕捉(Capture)。前…

pytorch的基本使用(上)

目录 一、安装pytorch1、用conda指令创建一个pytorch的环境2、安装pytorch&#xff08;无独显&#xff09; 二、编译器选择1、pycharm&#xff08;1&#xff09;安装pycharm&#xff08;2&#xff09;选择编译器&#xff08;3&#xff09;检测能否正常运行小技巧 pycharm 的创建…

【linux】解决报错:Network error: Connection refused

【linux】解决报错&#xff1a;Network error: Connection refused 【创作不易&#xff0c;求点赞关注收藏】&#x1f600; 一、问题描述 我现在使用MobaTerm远程连接服务器&#xff0c;但是出现了Network error: Connection refused报错&#xff0c;可能是我原先设置了一些…

计网-三次握手和四次挥手

TCP建立和断开连接的过程&#xff08;三次握手和四次挥手&#xff09; TCP通信的过程&#xff1a; 问题&#xff1a;tcp是如何保证数据在客户端和服务端之间通信传输的&#xff1f; 分为三个步骤&#xff1a;三次握手&#xff0c;传输数据确认&#xff0c;四次挥手。三次握手…

react的解构赋值

我最近在用react讨生活。我的感觉&#xff0c;react开发效率不高。这当然应该是我还不熟悉react的缘故。但是&#xff0c;在阅读react代码过程中&#xff0c;其中一个容易困惑的地方是它到处充斥着的解构赋值。当然了&#xff0c;解构赋值并不是React特有的功能&#xff0c;而是…

OpenCV距离变换函数distanceTransform的使用

操作系统&#xff1a;ubuntu22.04OpenCV版本&#xff1a;OpenCV4.9IDE:Visual Studio Code编程语言&#xff1a;C11 功能描述 distanceTransform是OpenCV库中的一个非常有用的函数&#xff0c;主要用于计算图像中每个像素到最近的背景&#xff08;通常是非零像素到零像素&…

tkinter-TinUI-xml实战(12)pip可视化管理器

引言 pip命令行工具在平常使用方面确实足够简单&#xff0c;本项目只是作为TinUI多界面开发的示例。 当然&#xff0c;总有人想用GUI版pip&#xff0c;实际上也有。不过现在&#xff0c;我们就来手搓一个基于python和TinUI&#xff08;tkinter&#xff09;的pip可视化管理器。…

数据结构——考研笔记(二)线性表的定义和线性表之顺序表

文章目录 二、线性表2.1 定义、基本操作2.1.1 知识总览2.1.2 线性表的定义2.1.3 线性表的基本操作2.1.4 知识回顾与重要考点 2.2 顺序表2.2.1 知识总览2.2.2 顺序表的定义2.2.3 顺序表的实现——静态分配2.2.4 顺序表的实现——动态分配2.2.5 知识回顾与重要考点2.2.6 顺序表的…

【分库】分库的设计与原则、数据分片策略、垂直分库与水平分库、数据库引擎选择与配置优化

目录 引言 分库设计原则 数据分片策略的选择 垂直分库 vs 水平分库的比较 数据库引擎选择与配置优化 引言 在面对日益增长的数据量和不断升级的业务需求时&#xff0c;传统的单体数据库架构往往难以应对高并发、大数据量带来的性能瓶颈。为了突破这些限制&#xff0c;分库…

godis源码分析——database存储核心1

前言 redis的核心是数据的快速存储&#xff0c;下面就来分析一下godis的底层存储是如何实现&#xff0c;先分析单机服务。 此文采用抓大放小原则&#xff0c;先大的流程方向&#xff0c;再抓细节。 流程图 源码分析 现在以客户端连接&#xff0c;并发起set key val命令为例…

vue3中谷歌地图+外网申请-原生-实现地址输入搜索+点击地图获取地址回显 +获取国外的geoJson实现省市区级联选择

一. 效果&#xff1a;输入后显示相关的地址列表&#xff0c;选中后出现标示图标和居中定位 1.初始化谷歌地图 在index.html加上谷歌api请求库 <script src"https://maps.googleapis.com/maps/api/js?key申请到的谷歌地图密钥&vweekly&librariesgeometry,place…

基于TCP的在线词典系统(分阶段实现)(阻塞io和多路io复用(select)实现)

1.功能说明 一共四个功能&#xff1a; 注册 登录 查询单词 查询历史记录 单词和解释保存在文件中&#xff0c;单词和解释只占一行, 一行最多300个字节&#xff0c;单词和解释之间至少有一个空格。 2.功能演示 3、分阶段完成各个功能 3.1 完成服务器和客户端的连接 servic…

Vue el-input 限制输入内容

&#x1f914;日常项目中经常遇到既要el-input的样式&#xff0c;又要el-input-number限制&#xff0c;所以需要绑定input事件进行约束输入限制。 以下使用自定义指令进行约束el-input输入的值&#xff0c;便于后期统一管理和拓展。 预览 代码 <!DOCTYPE html> <ht…

【机器学习】精准农业新纪元:机器学习引领的作物管理革命

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀目录 &#x1f50d;1. 引言&#x1f4d2;2. 精准农业的背景与现状&#x1f341;精准农业的概念与发展历程&#x1f342;国内外精准农业实践案…

【数据结构】手写堆 HEAP

heap【堆】掌握 手写上浮、下沉、建堆函数 对一组数进行堆排序 直接使用接口函数heapq 什么是堆&#xff1f;&#xff1f;&#xff1f;堆是一个二叉树。也就是有两个叉。下面是一个大根堆&#xff1a; 大根堆的每一个根节点比他的子节点都大 有大根堆就有小根堆&#xff1…

(南京观海微电子)——二极管应用及选取

二极管是 用半导体材料(硅、硒、锗等)制成的一种电子器件。二极管有两个电极&#xff0c;正极&#xff0c;又叫阳极&#xff1b;负极&#xff0c;又叫阴极&#xff0c;给二极管两极间加上正向电压时&#xff0c;二极管导通&#xff0c; 加上反向电压时&#xff0c;二极管截止。…

Vue1-Vue核心

目录 Vue简介 官网 介绍与描述 Vue的特点 与其它 JS 框架的关联 Vue周边库 初识Vue Vue模板语法 数据绑定 el与data的两种写法 MVVM模型 数据代理 回顾Object.defineProperty方法 何为数据代理 Vue中的数据代理 数据代理图示 事件处理 事件的基本使用 事件修…

【UE5.1】Chaos物理系统基础——06 子弹破坏石块

前言 在前面我们已经完成了场系统的制作&#xff08;【UE5.1】Chaos物理系统基础——02 场系统的应用_ue5&#xff09;以及子弹的制作&#xff08;【UE5.1 角色练习】16-枪械射击——瞄准&#xff09;&#xff0c;现在我们准备实现的效果是&#xff0c;角色发射子弹来破坏石柱。…

STM32智能空气质量监测系统教程

目录 引言环境准备智能空气质量监测系统基础代码实现&#xff1a;实现智能空气质量监测系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;空气质量监测与优化问题解决方案与优化收尾与总结 1. 引言 智能空…