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

news2024/11/15 7:55:43

串的顺序存储

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

计算串的长度

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

#define MAXLEN 255//预定义最大串为255

typedef 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; // 如果越界,返回false
    for (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; // 移动到下一个位置
        else
            return i; // 如果找到相等的子串,返回其在主串中的位置
    }
    return 0; // 如果循环结束还没有找到子串,返回0
}

 总结:

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

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

相关文章

接口安全配置

问题点&#xff1a; 有员工在工位在某个接口下链接一个集线器&#xff0c;从而扩展上网接口&#xff0c;这种行为在某些公司是被禁止的&#xff0c;那么网络管理员如何控制呢&#xff1f;可以配置接口安全来限制链接的数量&#xff0c;切被加入安全的mac地址不会老化&#xff…

开源模型应用落地-工具使用篇-Spring AI-Function Call(八)

​​​​​​​一、前言 通过“开源模型应用落地-工具使用篇-Spring AI&#xff08;七&#xff09;-CSDN博客”文章的学习&#xff0c;已经掌握了如何通过Spring AI集成OpenAI和Ollama系列的模型&#xff0c;现在将通过进一步的学习&#xff0c;让Spring AI集成大语言模型更高阶…

Linux的世界 -- 初次接触和一些常见的基本指令

一、Linux的介绍和准备 1、简单介绍下Linux的发展史 1991年10月5日&#xff0c;赫尔辛基大学的一名研究生Linus Benedict Torvalds在一个Usenet新闻组(comp.os.minix&#xff09;中宣布他编制出了一种类似UNIX的小操作系统&#xff0c;叫Linux。新的操作系统是受到另一个UNIX的…

【Python】爬虫实战01:获取豆瓣Top250电影信息

本文中我们将通过一个小练习的方式利用urllib和bs4来实操获取豆瓣 Top250 的电影信息&#xff0c;但在实际动手之前&#xff0c;我们需要先了解一些关于Http 请求和响应以及请求头作用的一些知识。 1. Http 请求与响应 HTTP&#xff08;超文本传输协议&#xff09;是互联网上…

C#创建windows服务程序

步骤 1: 创建Windows服务项目 打开Visual Studio。选择“创建新项目”。在项目类型中搜索“Windows Service”并选择一个C#模板&#xff08;如“Windows Service (.NET Framework)”&#xff09;&#xff0c;点击下一步。输入项目名称、位置和其他选项&#xff0c;然后点击“创…

C++ | Leetcode C++题解之第232题用栈实现队列

题目&#xff1a; 题解&#xff1a; class MyQueue { private:stack<int> inStack, outStack;void in2out() {while (!inStack.empty()) {outStack.push(inStack.top());inStack.pop();}}public:MyQueue() {}void push(int x) {inStack.push(x);}int pop() {if (outStac…

秋招突击——7/9——MySQL索引的使用

文章目录 引言正文B站网课索引基础创建索引如何在一个表中查看索引为字符串建立索引全文索引复合索引复合索引中的排序问题索引失效的情况使用索引进行排序覆盖索引维护索引 数据库基础——文档资料学习整理创建索引删除索引创建唯一索引索引提示复合索引聚集索引索引基数字符串…

网络安全——防御课实验二

在实验一的基础上&#xff0c;完成7-11题 拓扑图 7、办公区设备可以通过电信链路和移动链路上网(多对多的NAT&#xff0c;并且需要保留一个公网IP不能用来转换) 首先&#xff0c;按照之前的操作&#xff0c;创建新的安全区&#xff08;电信和移动&#xff09;分别表示两个外网…

基础小波降噪方法(Python)

主要内容包括&#xff1a; Stationary wavelet Transform (translation invariant) Haar wavelet Hard thresholding of detail coefficients Universal threshold High-pass filtering by zero-ing approximation coefficients from a 5-level decomposition of a 16Khz …

win10系统更新后无法休眠待机或者唤醒,解决方法如下

是否使用鼠标唤醒 是否使用鼠标唤醒 是否使用键盘唤醒

【Java开发实训】day03——方法的注意事项

目录 一、方法的基本概念 二、void和return关键字 三、单一返回点原则 四、static方法使用说明 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &#x1f4a1;本文由Filotimo__✍️原创&#xff0c;首发于…

《Windows API每日一练》9.25 系统菜单

/*------------------------------------------------------------------------ 060 WIN32 API 每日一练 第60个例子POORMENU.C&#xff1a;使用系统菜单 GetSystemMenu函数 AppendMenu函数 (c) www.bcdaren.com 编程达人 -------------------------------------------…

Java02--基础概念

一、注释 注释是在程序指定位置添加的说明性信息 简单理解&#xff0c;就是对代码的一种解释 1.单行注释 格式: //注释信息 2.多行注释 格式: /*注释信息*/ 3.文档注释 格式: /**注释信息*/ 注释使用的细节: 注释内容不会参与编译和运…

九盾安防丨如何判断叉车是否超速?

在现代物流和生产流程中&#xff0c;叉车是提高效率和降低成本的关键工具。然而&#xff0c;叉车的高速行驶也带来了安全隐患&#xff0c;这就要求我们对其进行严格的安全管理。九盾安防&#xff0c;作为业界领先的安防专家&#xff0c;今天就为大家揭晓如何判断叉车是否超速&a…

OpenCV距离变换函数distanceTransform的使用

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

VMware_centos8安装

目录 VMware Workstation Pro的安装 安装centos VMware Workstation Pro的安装 正版VMware 17百度网盘下载链接 (含秘钥) 链接&#xff1a;https://pan.baidu.com/s/16zB-7IAACM_1hwR1nsk12g?pwd1111 提取码&#xff1a;1111 第一次运行会要求输入秘钥 秘钥在上边的百度网盘…

【Leetcode】最小数字游戏

你有一个下标从 0 开始、长度为 偶数 的整数数组 nums &#xff0c;同时还有一个空数组 arr 。Alice 和 Bob 决定玩一个游戏&#xff0c;游戏中每一轮 Alice 和 Bob 都会各自执行一次操作。游戏规则如下&#xff1a; 每一轮&#xff0c;Alice 先从 nums 中移除一个 最小 元素&…

docker安装nginx并配置https

参考 docker安装nginx并配置https-腾讯云开发者社区-腾讯云 (tencent.com) 证书的生成 参见&#xff1a;SpringBoot项目配置HTTPS接口的安全访问&#xff08;openssl配置&#xff09;_配置接口访问-CSDN博客 步骤 1: 拉取Nginx镜像 docker pull nginx 好使的镜像如下&#x…

DockerCompose拉取DockerHub镜像,并部署OpenMetaData

参考博主&#xff1a;http://t.csdnimg.cn/i49ET 一、DockerCompose拉取DockerHub镜像 方法一&#xff08;不太行&#xff09;&#xff1a; 在daemon.json文件中添加一些国内还在服务的镜像站&#xff08;可能某些镜像会没有&#xff09; ([ -f /etc/docker/daemon.json ] ||…

RK3568笔记三十五:LED驱动开发测试

若该文为原创文章&#xff0c;转载请注明原文出处。 字符设备驱动程序的基本框架&#xff0c;主要是如何申请及释放设备号、添加以及注销设备&#xff0c;初始化、添加与删除 cdev 结构体&#xff0c;并通过 cdev_init 函数建立 cdev 和 file_operations 之间的关联&#xff0c…