数据结构第三章--串

学习视频:天勤考研
语言:c++
string容器总结:c++中string容器的常用方法总结,加深学习巩固

1.串的基础

串分为顺序存储结构和链式存储结构
但是考研链式存储结构,不会出现,所有我只考虑顺序存储结构。

顺序存储结构分为:定长存储结构和变长存储结构

定长存储结构(存储的长度是不变的):

typedef struct
{
    char str[maxSize+1];
    int length;
}Str;

maxSize为已经定义的常量,表示串的最大长度;str数组的长度定义为maxSize+1,是因为char类会多出一个'\0'作为结束标记。

关于可以用length来返回串的长度,为什么还要定义maxSize来占内存空间呢?
答:当需要立马读出串的长度,或结束标记时使用,定义maxSize 可以大大方便的代码实现。

变长存储结构(可以自行设置串的长度):

typedef struct
{
    char *ch;
    int length;
}Str;

变长存储结构申请内存:

Str s;
s.length=10;  //设置串的长度 
s.ch=new char[s.length+1];  //用new来申请内存,也可以使用malloc()来申请
s.ch[0]='1';  //赋值
cout<<s.ch[0]<<endl;  //打印
free(s.ch);    //释放内存

关于new和malloc申请函数的区别:

//malloc函数
Str s;
s.length=10;
s.ch=(char *)malloc((s.length+1)*sizeof(char)); 自己计算所需要开辟的内存大小
 
//new函数
Str s;
s.length=10;
s.ch=new char[s.length+1];   //此处只需要确定int数组的大小,而所需要的内存空间有系统自动计算

2.串的基本结构(这里以变长存储结构为例)

1.赋值操作

功能类似于string容器的assign操作。
string str4;str4.assign("hello c++");

#include <bits/stdc++.h>
using namespace std;

typedef struct
{
    char *ch;
    int length;
}Str;

int strAssign(Str& str,char ch[])
{
	//当str.ch已经指向一个存储空间(已经存储数据)的时候,我们可以用这个操作将存储空间释放掉。
    if(str.ch)
        delete str.ch;
    int len=0;
    char *c=ch;
    //判断ch中元素的长度
    while(*c)
    {
        ++len;
        ++c;
    }
	//传入的ch为空时
    if(len==0) {
        str.ch=NULL;
        str.length=0;
        return 1;
    }
    else{
        str.ch=new char[len+1];
        //当内存分配失败时
        if(str.ch==NULL)
            return 0;
        else{
            c=ch;
            for(int i=0;i<=len;++i,++c){
                str.ch[i]=*c;
            }
            str.length=len;
            return 1;
        }
    }
}

int main(){
    Str s;
    s.length=10;
    s.ch=new char[s.length+1];
    char ch[20]={0};
    string name="abcd";
    strcpy(ch,name.c_str());
    strAssign(s,ch);   
    cout<<s.length<<endl;
    cout<<s.ch<<endl;
}

2.取串长度

int strLength(Str str)
{
	return str.length;
}

3.串比较

这个功能和string容器的compare方法类似。
比较规则
设两串C1和C2中待比较字符分别为a和b:
1.如果a的ASCII码小于b的ASCII码,则返回C1小于C2标记(一个负数);
2.如果a的ASCII码大于b的ASCII码,则返回C1大于C2标记(一个正数);
3.如果a的ASCII码等于b的ASCII码,则按照之前的规则继续比较两串中下一对字符;
4.经过上述步骤没有比较出C1和C2大小的情况下,先结束的串为较小串,两串同时结束则返回两串相等标记(0)。

比较代码:

int strCompare(Str s1,Str s2)
{
    for(int i=0;i<s1.length&&i<s2.length;++i)
        if(s1.ch[i]!=s2.ch[i])
            return s1.ch[i]-s2.ch[i];
    return s1.length-s2.length;
}

总共代码:

#include <bits/stdc++.h>
using namespace std;

typedef struct
{
    char *ch;
    int length;
}Str;

int strAssign(Str& str,char ch[])
{
    if(str.ch)
        delete str.ch;
    int len=0;
    char *c=ch;
    while(*c)
    {
        ++len;
        ++c;
    }

    if(len==0) {
        str.ch=NULL;
        str.length=0;
        return 1;
    }
    else{
        str.ch=new char[len+1];
        if(str.ch==NULL)
            return 0;
        else{
            c=ch;
            for(int i=0;i<=len;++i,++c){
                str.ch[i]=*c;
            }
            str.length=len;
            return 1;
        }
    }
}


int strCompare(Str s1,Str s2)
{
    for(int i=0;i<s1.length&&i<s2.length;++i)
        if(s1.ch[i]!=s2.ch[i])
            return s1.ch[i]-s2.ch[i];
    return s1.length-s2.length;
}

int main(){
    Str s1,s2;
    char ch[20]={0};

    string name="abcd";
    strcpy(ch,name.c_str());
    strAssign(s1,ch);   
    
    string name2="abcdf";
    strcpy(ch,name2.c_str());
    strAssign(s2,ch);

    if(strCompare(s1,s2)>0){
        cout<<"s1>s2"<<endl;
    }else if(strCompare(s1,s2)<0){
        cout<<"s1<s2"<<endl;
    }else 
        cout<<"s1==s2"<<endl;
}

结果:
在这里插入图片描述

4.串连接

功能与string串的append方法类似。

#include <bits/stdc++.h>
using namespace std;

typedef struct
{
    char *ch;
    int length;
}Str;

int strAssign(Str& str,char ch[])
{
    if(str.ch)
        delete str.ch;
    int len=0;
    char *c=ch;
    while(*c)
    {
        ++len;
        ++c;
    }

    if(len==0) {
        str.ch=NULL;
        str.length=0;
        return 1;
    }
    else{
        str.ch=new char[len+1];
        if(str.ch==NULL)
            return 0;
        else{
            c=ch;
            for(int i=0;i<=len;++i,++c){
                str.ch[i]=*c;
            }
            str.length=len;
            return 1;
        }
    }
}

//拼接操作
int append(Str& str,Str str1,Str str2){
    if(str.ch){
        free(str.ch);
        str.ch=NULL;
    }
    str.ch=new char[str1.length+str2.length+1];
    if(!str.ch)
        return 0;
    int i=0;
    while(i<str1.length)
    {
        str.ch[i]=str1.ch[i];
        ++i;
    }
    int j=0;
    while(j<=str2.length)
    {
        str.ch[i+j]=str2.ch[j];
        ++j;
    }
    str.length=str1.length+str2.length;
    return 1;
}

int main(){
    Str s,s1,s2;
    char ch[20]={0};

    string name="abcd";
    strcpy(ch,name.c_str());
    strAssign(s1,ch);   
    
    string name2="abcdf";
    strcpy(ch,name2.c_str());
    strAssign(s2,ch);

    append(s,s1,s2);
    cout<<s.ch<<endl;
}

结果:
在这里插入图片描述

5.子串的获取

功能与string容器的substr方法功能类似

#include <bits/stdc++.h>
using namespace std;

typedef struct
{
    char *ch;
    int length;
}Str;

int strAssign(Str& str,char ch[])
{
    if(str.ch)
        delete str.ch;
    int len=0;
    char *c=ch;
    while(*c)
    {
        ++len;
        ++c;
    }

    if(len==0) {
        str.ch=NULL;
        str.length=0;
        return 1;
    }
    else{
        str.ch=new char[len+1];
        if(str.ch==NULL)
            return 0;
        else{
            c=ch;
            for(int i=0;i<=len;++i,++c){
                str.ch[i]=*c;
            }
            str.length=len;
            return 1;
        }
    }
}

//pos指子串开始位置,len表示子串长度
int subString(Str& substr,Str str,int pos,int len)
{
    if(pos<0||pos>str.length||len<0||len>str.length-pos)
        return 0;
    if(substr.ch)
    {
        delete substr.ch;
        substr.ch=NULL;
    }
    if(len==0){
        substr.ch=NULL;
        substr.length=0;
        return 1;
    }
    else{
        substr.ch=new char[len+1];
        int i=pos;
        int j=0;
        while(i<pos+len)
        {
            substr.ch[j]=str.ch[i];
            ++i;
            ++j;
        }
        substr.ch[j]='\0';
        substr.length=len;
        return 1;
    }
}

int main(){
    Str s,s1,s2;
    char ch[20]={0};  
    
    string name2="abcdf";
    strcpy(ch,name2.c_str());
    strAssign(s2,ch);

    subString(s,s2,1,3);
    cout<<s.ch<<endl;
}

结果:
在这里插入图片描述

6.清空串

与string的clear方法类似

int clearString(Str& str)
{
	if(str.ch)
	{
		delete str.ch;
		str.ch=NULL;
	}
	str.length=0;
	return 1;

3.KMP算法

KMP算法详解

#include<bits/stdc++.h>
using namespace std;

/**
 * KMP算法主要用来快速查找主串中是否有与模式串中相同的串。
 * 使用KMP算法的优点:可以避免回调,缩短运行时间
 * 模式串的第一个元素的下标为1,这样主要是方便于操作
 * next[],next数组的意思就是 next[i] = len; 长度为i的数组的前缀和后缀相等的最大长度。 
 * nextval是改进的next,避免了aaaab这种情况,b前面都是相同的元素,使用nextval可以简化这种情况
 * **/

typedef struct
{
    char *ch;
    int length;
}Str;


int strAssign(Str& str,char ch[])
{
    if(str.ch)
        delete str.ch;
    int len=0;
    char *c=ch;
    while(*c)
    {
        ++len;
        ++c;
    }

    if(len==0) {
        str.ch=NULL;
        str.length=0;
        return 1;
    }
    else{
        str.ch=new char[len+1];
        if(str.ch==NULL)
            return 0;
        else{
            c=ch;
            for(int i=1;i<=len+1;++i,++c){
                str.ch[i]=*c;
            }
            str.length=len;
            return 1;
        }
    }
}


//next[],next数组的意思就是 next[i] = len; 长度为i的数组的前缀和后缀相等的最大长度。 
void getNext(Str substr,int next[])
{
    int j=1,t=0;
    next[1]=0;
    while(j<substr.length)
    {
        if(t==0||substr.ch[j]==substr.ch[t])
        {
            next[j+1]=t+1;
            t++;
            j++;
        }else{
            t=next[t];
        }
    }
}


//nextval是改进的next,避免了aaaab这种情况,b前面都是相同的元素,使用nextval可以简化这种情况
void getNextVal(Str substr,int nextval[],int next[])
{
    int j=1,t=0;
    next[1]=0;
    nextval[1]=0;
    while(j<substr.length)
    {
        if(t==0||substr.ch[j]==substr.ch[t])
        {
            next[j+1]=t+1;
            if(substr.ch[j+1]!=substr.ch[next[j+1]])
                nextval[j+1]=next[j+1];
            else    
                nextval[j+1]=nextval[next[j+1]];
            t++;
            j++;
        }else{
            t=nextval[t];
        }
    }
}

//KMP算法,这里返回值为匹配串第一个元素地址
int KMP(Str str,Str substr,int next[])
{
    int i=1,j=1;
    while(i<=str.length&&j<=substr.length)
    {
        if(j==0||str.ch[i]==substr.ch[j])
        {
            ++i;
            ++j;
        }
        else
        {
            j=next[j];
        }
    }
    if(j>substr.length)
        return i-substr.length;
    else
        return 0;
}
int main(){
     Str s1,s2;
    char ch[20]={0};
    int next[100];
    int nextval[100];

    string name="abbaababa";
    strcpy(ch,name.c_str());
    strAssign(s1,ch);   
    
    string name2="aab";
    strcpy(ch,name2.c_str());
    strAssign(s2,ch);

    getNext(s2,next);
    cout<<KMP(s1,s2,next)<<endl;

    getNextVal(s2,nextval,next);
    cout<<KMP(s1,s2,nextval)<<endl;;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
数据结构与算法分析-C语言描述(原书第二版)是一本经典的计算机科学教材,它涵盖了数据结构和算法的基本概念和实现方法。下面是第五章的练习题答案: 1. 编写一个递归算法,计算一个整数n的阶乘。 ```c #include <stdio.h> int factorial(int n) { if (n == 0) { return 1; } else { return n * factorial(n-1); } } int main() { int n = 5; printf("Factorial of %d is %d\n", n, factorial(n)); return 0; } ``` 2. 编写一个递归算法,输出一个整数n的二进制表示。 ```c #include <stdio.h> void decimalToBinary(int n) { if (n > 0) { decimalToBinary(n / 2); printf("%d", n % 2); } } int main() { int n = 10; printf("Decimal %d is binary ", n); decimalToBinary(n); printf("\n"); return 0; } ``` 3. 编写一个非递归算法,求一个数组的最大值。 ```c #include <stdio.h> int findMax(int arr[], int size) { int max = arr[0]; for (int i = 1; i < size; i++) { if (arr[i] > max) { max = arr[i]; } } return max; } int main() { int arr[] = {2, 8, 4, 1, 6}; int size = sizeof(arr) / sizeof(arr[0]); printf("The maximum value in the array is %d\n", findMax(arr, size)); return 0; } ``` 4. 编写一个非递归算法,将一个字符串进行反转。 ```c #include <stdio.h> #include <string.h> void reverseString(char str[]) { int len = strlen(str); for (int i = 0, j = len - 1; i < len / 2; i++, j--) { char temp = str[i]; str[i] = str[j]; str[j] = temp; } } int main() { char str[] = "Hello World"; printf("Original string: %s\n", str); reverseString(str); printf("Reversed string: %s\n", str); return 0; } ``` 以上是第五章的练习题答案,希望对您有帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值