数据结构笔记整理第4章:字符串和矩阵

来源:互联网 发布:卸载软件设置密码 编辑:程序博客网 时间:2024/06/05 14:27

第4章 字符串和矩阵

本章内容

本章主要介绍字符串以及数据结构中矩阵的相关内容。

4.1 字符串的基本概念

串的基本概念:串是由零个或者多个字符组成的有限序列。串中字符的个数称为串的长度,含有零个元素的串叫做空串。

串的长度问题:现在看一个例子:
我们声明了一个字符串str,并对其进行赋值:

char str[] = "abcdef";

串通常由一个字符数组来表示,因此在这里str所占的内存字符为:a,b,c,d,e,f,\0,其中\0是编译器识别串结束。而串内字符为:a,b,c,d,e,f。因此,串str的长度为6,数组str的长度为7。

4.2 字符串的定义与相应算法

我们提到的字符串主要由字符数组来实现,因此算法的方式与顺序栈、顺序队列等结构相似。
【定义1】串的定义

#define maxSize 100     //定义串的最大长度为100typedef struct Str {    cbar ch[maxSize+1]; //存放元素的字符数组,多一个用来存放\0    int length;         //串顶指针}Str;

串的匹配算法。这里我们介绍两种算法,第一种是非常简单的模式匹配算法,第二种是KMP算法。两种算法都是用来判断子串是否为主串的一个部分。如果是则返回其在主串中的位置,不是则返回-1。

【算法1】简单匹配算法
算法的基本思想非常简单:从主串的第一个位置起和子串的第一个字符开始比较,如果相等,则继续逐一比较后面的字符,否则就从主串接下来的字符按照相同的方法开始比较,以此类推直到比较完主串所有的字符。

int index(Str str, Str substr) {    int i = 0, j = 0, k = i;    while(i < str.length && j < substr.length) {        if (str.ch[i] == substr.ch[j]) {            ++i;            ++j;        }        else {            j = 0;            i = ++k;        }    }       if (j == substr.length) {        return k;    }    return k-1;}

**【算法2】**KMP算法
KMP算法的核心理念是充分利用已经改进计算过的结果,不回溯i。想办法通过调整j的位置从而消除i处的不匹配,从而使得匹配可以继续进行。
求next数组:假设S串长度为n,下标范围0~n-1,穷举所有串对a和b,a为0~k-1的子串,b为n-k~n-1的子串,a与b匹配。取最长的一个串作为结果,即next[n] = k
由于考研中对KMP算法掌握要求很低,这里就只给出其源码,关于算法的详细讲解会另写博客讨论。

#include <iostream>using namespace std;int KMP(Str str, Str substr, int next[]);void getNext(Str substr, int next[]);int main() {    Str str = "ABABABABABABAAAA";    Str substr = "BABA";    int next[maxSize];    getNext(substr, next);    int result = KMP(str, substr, next);    return 0;}int KMP(Str str, Str substr, int next[]) {    int i = 0, j = 0;    while(i < str.length && j < substr.length) {        if (str.ch[i]==substr.ch[j]) {            ++i;            ++j;        }        else {            j = next[j];            if (j == -1) {                j = 0;                ++i;            }        }    }    if (j == substr.length) {        return i-substr.length;    }    return -1;}void getNext(Str substr, int next[]) {    int i = 0, j = -1;    next[0] = -1;    while(i < substr.length) {        if (j == -1 || substr.ch[i] == substr.ch[j]) {            ++i;            ++j;            next[i] = j;        }        else {            j = next[j];        }    }}

4.3 矩阵

这里提到的矩阵主要是指二维的数组,我们会介绍矩阵的一些常见算法和稀疏矩阵的概念。

4.3.1 矩阵的运算

【算法3】矩阵的转置

void transMat(int A[][max], int B[][max], int m, int n) {    int i, j;    for (i = 0; i < m; ++i) {        for (j = 0; j < n; ++j) {            B[j][i] = A[i][j];        }    }}

【算法4】矩阵相加

void addMat(int C[][max], int A[][max], int B[][max], int m, int n) {    int i, j;    for (i = 0; i < m; ++i) {        for (j = 0; j < n; ++j) {            C[i][j] = A[i][j] + B[i][j];        }    }}

【算法5】矩阵相乘

void mulMat(int C[][max], int A[][max], int B[][max], int m, int n, int k) {    int i, j, h;    for (i = 0; i < m; ++i) {        for (j = 0; j < n; ++j) {            C[i][j] = 0;            for (h = 0; h < k; ++h) {                C[i][j] += A[i][h] * B[h][j];            }        }    } }
4.3.2 稀疏矩阵

尺寸为m*n的矩阵A有K个非零的元素,若K << m*n,则称A为稀疏矩阵。

三元组表示法:

typedef struct Trimat {    int value;    int i;    int j;}Trimat;Triamat trimat[5];trimat[k].val   //第K个非零元素的值trimat[K].i, trimat[K].i    //第K个非零元素在矩阵中的下标

伪地址表示法:
按照行优先或者列优先,存储相对位置。需要2N个存储单元,N为非零元素的个数。对于一个m*n的稀疏矩阵中元素A[i][j]的伪地址计算方法:
n(i-1)+j,伪地址除以n得到i,取余得到j

邻接表表示法:
链式存储,每一行的非零元素串联成一个链表,不常考察。

0 0