数据结构与算法要点总结(4):数组、矩阵、字符串、广义表

本文概述了一维到多维数组的推广,包括特殊矩阵如对称矩阵和稀疏矩阵的存储优化,以及字符串的模式匹配(如KMP算法)和广义表的深度计算。重点介绍了数组的前驱后继个数计算和存储位置,以及广义表的笔试考点和操作技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1、总体概述

2、数组

前驱后继个数

计算存储位置:

​n维推广

 3、特殊矩阵

对称矩阵

计算存放位置:

三对角矩阵

稀疏矩阵

 4、字符串

串的模式匹配

朴素模式匹配

KMP算法

 5、广义表

笔试考点:

取出特定元素:

广义表深度:


1、总体概述

一维数组与一位数组的推广:一维数组与多维数组、特殊矩阵、稀疏矩阵。

线性表的运用:字符串。

广义表:一种递归形式的表。

2、数组

前驱后继个数

 二维数组a在存储器中有两种地址映射方式: 行优先、列优先

计算存储位置:

n维推广

 3、特殊矩阵

对称矩阵

为节约存储,只存对角线及对角线以上的元素,或者只存对角线或对角线以下的元素。前者称为上三角矩阵,后者称为下三角矩阵

计算存放位置:

考试时要注意i,j的大小关系,以及是从零开始,还是从一开始。

技巧:若是选择题,可以举几个例子,带入算算看。 

三对角矩阵

矩阵A中元素 A[i][j] 在 B 中位置为 k = 2*i + j。

稀疏矩阵

在存储稀疏矩阵时,为节省存储空间,应只存储非零元素。

三元组表示(数组存储)

注意存储顺序,普通转置算法,快速转值算法。

用正交链表表示稀疏矩阵

 4、字符串

注意:空串和空白串不同,例如" """分别表示长度为1的空白串和长度为0的空串。

串的模式匹配

朴素模式匹配

KMP算法

可以观看代码中左神的视频。。

#include<iostream>
#include<string>
using namespace std;

/*   https://www.bilibili.com/video/BV13g41157hK/?p=13&spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=b35eaf7c60912cc5b98163708d14772c  */

int* getNextArray(const string& p) {
    int m = p.length();
    int* next = new int[m];
    next[0] = -1;
    if (m == 1) {
        return next;
    }
    next[1] = 0;
    int i = 2, cn = 0;
    while (i < m) {
        if (p[i - 1] == p[cn]) {
            next[i++] = ++cn;
        } else if (cn > 0) {
            cn = next[cn];
        } else {
            next[i++] = 0;
        }
    }
    // next数组 ----> 第 n 位存储的是 0 ~ (n - 1) 这串字符 前缀 和 后缀 相等的最长的串的长度,注意前后缀都不能取整体
    // for (int i = 0; i < m; i++) {
    //     cout << next[i] << " ";
    // }
    // cout << endl;
    return next;
}

int KMP(const string& str1, const string& str2) {
    if (str1.length() < str2.length() || str2.length() < 1 || str1.length() < 1) {
        return -1;
    }
    int i1 = 0, i2 = 0;
    int* nextArr = getNextArray(str2);
    while (i1 < str1.length() && i2 < str2.length()) {
        if (str1[i1] == str2[i2]) {
            i1++;
            i2++;
        } else if (i2 == 0) {  // nextArr[i2] == -1
            i1++;
        } else {
            i2 = nextArr[i2];
        }
    }
    delete[] nextArr;
    return i2 == str2.length() ? i1 - i2 : -1;
}

int main() {
    string str1 = "aaaaaabaaaaaaab";
    string str2 = "abcabcabcd";
    cout << KMP(str1, str2) << endl;
    system("pause");
    return 0;
}

next的定义:默认next[0] = -1

迅速的求法:

先求PM表,再把PM表右移1位。

01234567
abaabcac
PM00112010
标准next:PM右移-10011201
下述板子的next:PM减1-1-1001-10-1

好背的板子:但是next和标准next不同,可以用作机试准备

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

// 构建 next 数组,模式串 pattern
void buildNext(const string& pattern, vector<int>& next) {
    int m = pattern.size();
    next.resize(m);
    next[0] = -1; // 约定:next[0] = -1
    int j = -1; // 指向前缀末尾的指针
    for (int i = 1; i < m; i++) {
        // 若不匹配,向前回退
        while (j != -1 && pattern[i] != pattern[j + 1]) {
            j = next[j];
        }
        // 若匹配,扩展前后缀长度
        if (pattern[i] == pattern[j + 1]) {
            j++;
        }
        next[i] = j;
    }
}

// KMP 主算法,返回所有匹配的起始位置(支持多次匹配)
vector<int> KMP(const string& text, const string& pattern) {
    vector<int> next;
    buildNext(pattern, next);
    for (auto c : pattern) {
        cout << c << " ";
    }
    cout << endl;
    for (auto num : next) {
        cout << num << " ";
    }
    cout << endl;
    vector<int> result;
    int n = text.size(), m = pattern.size();
    int j = -1;
    for (int i = 0; i < n; i++) {
        // 若不匹配,跳转
        while (j != -1 && text[i] != pattern[j + 1]) {
            j = next[j];
        }
        // 若匹配,继续推进
        if (text[i] == pattern[j + 1]) {
            j++;
        }
        // 完全匹配
        if (j == m - 1) {
            result.push_back(i - m + 1); // 记录匹配起点
            j = next[j]; // 准备继续匹配后续
        }
    }
    return result;
}

int main() {
    string text = "ababcabababcbab";
    string pattern = "abaabcac";
    vector<int> matchPositions = KMP(text, pattern);
    for (int pos : matchPositions) {
        cout << "Pattern found at index: " << pos << endl;
    }
    system("pause");
    return 0;
}

 5、广义表

笔试考点:

深度,长度,表头,表尾

特别注意:表尾是一个表,需要额外自己加一层括号

取出特定元素:

广义表深度:

笔试的时候找括号层数最多的就可以了 。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值