数组和字符串中的数据结构和算法(上)

入门题看string match

在这里插入图片描述
两种比较容易实现的字符串实现算法,
假设在长度n的母串中匹配长度为m的字符串
1 暴力求解:顺序遍历母串,将每个字符作为匹配的起始字符,判读是否匹配字串。算法复杂度m*n。
代码的讲解,在注释中

#include <string.h>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
    char* StrStr(const char* str, const char* target)
    {
        if (!*target)//判断是否为空,c语言判断字符串为空,一般是取一个星号,跟\0比较,
        {
            return str;
        }
        char* p1Begin = p1, * p2 = (char*)target;//p1,p2两个指针,p1begin相当于临时存储了p1的位置,p2永远指向target开始的位置
        while (p1 && p2 && *p1 == *p2)//p1存在,p2存在,并且两个值相等。
        {
            p1++;
            p2++;
        }
        if (!*p2)//如果说p2走到了末位,就代表有
        {
            return p1Begin;//此时p1已经走完了
        }
        p1 = p1Begin + 1;//p1这个字符串默认向后走一个
        return NULL;
    }
}

2 Rabin-Karp
Rabin-Karp算法的思想:

假设子串的长度为M,目标字符串的长度为N
计算子串的hash值
计算目标字符串中每个长度为M的子串的hash值(共需要计算N-M+1次)
比较hash值
如果hash值不同,字符串必然不匹配,如果hash值相同,还需要使用朴素算法再次判断

d取字符集的个数
#define d 256 

/*  S  -> Search Sequence
    T  -> Target Sequence
    q  -> A prime number
*/
void search(char* S, char* T, int q) {
    int M = strlen(S);
    int N = strlen(T);
    int i, j;
    int SHashValue = 0;  // hash value for Search Sequence
    int THashValue = 0;  // hash value for Target Sequence
    int h = 1;           // h 的计算公式:pow(d, M-1) % q

    //计算h
    for (i = 0; i < M - 1; i++)
        h = (h * d) % q;

    // Calculate the hash value of Search Sequence
    for (i = 0; i < M; i++)
    {
        SHashValue = (d * SHashValue + S[i]) % q;
        THashValue = (d * THashValue + T[i]) % q;
    }

    // Slide the pattern over text one by one 
    for (i = 0; i <= N - M; i++) {
        // Chaeck the hash values of current T and S
        // If the hash values match then only check for characters on by one
        if (SHashValue == THashValue) {
            /* Check for characters one by one */
            for (j = 0; j < M; j++) {
                if (txt[i + j] != pat[j])
                    break;
            }
            if (j == M) {    // if SHashValue == THashValue and S[0...M-1] = T[i, i+1, ...i+M-1]
                cout << "Pattern found at index " << i << endl;
            }
        }

        // Calulate hash value for next text: Remove leading digit, 
        // add trailing digit           
        if (i < N - M)
        {
            THashValue = (d * (THashValue - T[i] * h) + T[i + M]) % q;
            // We might get negative value of THashValue, converting it to positive
            if (THashValue < 0)
                THashValue = (THashValue + q);
        }
    }
}

如果我们要在 ASCII 字符集范围内查找“搜索词”,由于 ASCII 字符集中有 128 个字符,那么 M 就等于 128,比如我们要在字符串 “abcdefg” 中查找 “cde”,那么我们就可以将搜索词 “cde” 转化为“("c"的码点 * M + "d"的码点) * M + "e"的码点 = (99 * 128 + 100) * 128 + 101 = 1634917”这样一个数值。

分析一下这个数值:1634917,它可以代表字符串 “cde”,其中:

代表字符 “c” 的部分是“ "c"的码点 * (M 的 n - 1 次方) = 99 * (128 的 2 次方) = 1622016”

代表字符 “d” 的部分是“ "d"的码点 * (M 的 n - 2 次方) = 100 * (128 的 1 次方) = 12800”

代表字符 “e” 的部分是“ "e"的码点 * (M 的 n - 3 次方) = 101 * (128 的 0 次方) = 101”

(n 代表字符串的长度)

我们可以随时减去其中一个字符的值,也可以随时添加一个字符的值。

“搜索词”计算好了,那么接下来计算“源串”,取“源串”的前 n 个字符(n 为“搜索词”的长度)”abc”,按照同样的方法计算其数值: ("a"的码点 * M + "b"的码点) * M + "c"的码点 = (97 * 128 + 98) * 128 + 99 = 1601891

然后将该值与“搜索词”的值进行比较即可。比较发现 1634917 与 1601891 不相等,则说明 “cde” 与 “abc” 不匹配,则继续向下寻找,下一步应该比较 “cde” 跟 “bcd” 了,那么我们如何利用前一步的信息呢?首先去掉 “abc” 的数值中代表 a 的部分: (1601891 - "a"的码点 * (M 的 n - 1 次方)) = (1601891 - 97 * (128 的 2 次方)) = 12643

然后再将结果乘以 M(这里是 128),再加上 “d” 的码点值不就成了 “bcd” 的值了吗:

12643 * 128 + "d"的码点 = 1618304 + 100 = 1618404

这样就可以继续比较 “cde” 和 “bcd” 是否匹配,以此类推。

Array

int array[arraysize]//在堆上定义长度为arraysize的整型数组。
int *array=new int [arraysize]

Stack (栈)VS heap(堆)

stack 主要是由操作系统自动管理的空间,当进入一个函数后,操作系统会为函数函数自动分配存储空间,当函数返回时,系统会弹出内存块,根据指针回到前一个内存块,所以,栈总是以后进先出的工作方式工作
heap是用来储存动态分布的存储空间,程序员可以进行手动的对内存进行分配和回收,否则会引起内存泄漏

二维数组

在这里插入图片描述
好处是可以通过下标去访问元素,数组这种数据结构不适合分拣元素,如果想要分拣元素,那么应该使用vector元素,对于vector的访问元素,后面博客会给出用法。

Hash table

哈希表(HashTable)又叫做散列表,是根据关键码值(即键值对)而直接访问的数据结构。也就是说,它通过把关键码映射到表中一个位置来访问记录,以加快查找速度

拉链法

在这里插入图片描述
它是通过一种辅助的数据结构,把相同的元素进行连接起来,例如John Smith 和Sandra Dee哈希值相同,把 Sandra Dee链接到了John Smith的后面,这种方式实现比较简单,但是它的空间利于率是小于下面的线性搜索法的

线性搜索法

在这里插入图片描述

线性搜索法就是这个意思,如图示,如果有两个哈希值相同的情况下,例如,John Smith 和Sandra Dee
对应的哈希值都为152,那么Sabdra Dee就会往后走,自动寻找空位,就行补齐

在这里插入图片描述
参考文章:
https://blog.csdn.net/seacowtech/article/details/79256299

https://blog.csdn.net/iva_brother/article/details/82253989

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值