【数据结构】串与数组

【数据结构】串与数组

Problem A 三元组顺序表表示的稀疏矩阵转置运算Ⅰ

题目

Problem A

7-1 三元组顺序表表示的稀疏矩阵转置运算Ⅰ

全屏浏览题目切换布局

作者 王东

单位 贵州师范学院

三元组顺序表表示的稀疏矩阵转置。

输入格式:

输入第1行为矩阵行数m、列数n及非零元素个数t。
按行优先顺序依次输入t行,每行3个数,分别表示非零元素的行标、列标和值。

输出格式:

输出转置后的三元组顺序表结果,每行输出非零元素的行标、列标和值,行标、列标和值之间用空格分隔,共t行。

输入样例1:
3 4 3
0 1 -5
1 0 1
2 2 2
输出样例1:
0 1 1
1 0 -5
2 2 2

思路

使用三元组表示稀疏矩阵中的非零元素,进而创建一个三元组数组data[]来存储稀疏矩阵中的所有非零元素。**预先确定矩阵M中每一列(即T中的每一行)的第一个非零元在T的data[]数组中的位置,则在对M的data[]数组中的三元组依次作转置时,能够直接把该非零元素放到T的data[]数组中的恰当位置。**最后输出结果即可。

代码

#include <iostream>
using namespace std;

typedef int ElemType;
#define MAXSIZE 100 // 非零元个数的最大值

struct Triple {
    int i, j; // 行下标和列下标
    ElemType e; //非零元素值
};

struct TSMatrix {
    Triple data[MAXSIZE]; // 非零元三元组表,data[0]未用
    int rows, columns, num; // 矩阵行数、列数和非零元个数
};

/// @brief 创建稀疏矩阵M
/// @param M 
void CreateSMatrix(TSMatrix &M) {
    int i, m, n;
    ElemType e;
    scanf("%d %d %d", &M.rows, &M.columns, &M.num);
    for (i = 0; i < M.num; ++i) {
        scanf("%d %d %d", &m, &n, &e);
        M.data[i].i = m;
        M.data[i].j = n;
        M.data[i].e = e;
    }
}

/// @brief 输出稀疏矩阵M
/// @param M 
void PrintSMatrix(TSMatrix M) {
    for (int ind = 1; ind <= M.num; ++ind) {
        printf("%d %d %d\n", M.data[ind].i, M.data[ind].j, M.data[ind].e);
    }
}

/// @brief 快速求稀疏矩阵M的转置矩阵T
/// @param M 
/// @param T 
void FastTransposeSMatrix(TSMatrix M, TSMatrix &T) {
    int p = 0, q = 0, t = 0, col = 0;
    int num[M.columns]; // num[col]表示矩阵M中第col列中非零元的个数
    int cpot[M.columns]; // cpot[col]指示M中第col列的第一个非零元在b.data中的位置
    T.rows = M.columns;
    T.columns = M.rows;
    T.num = M.num;
    if (T.num) {
        // 设初值
        for (col = 0; col < M.columns; ++col) {
            num[col] = 0;
            cpot[col] = 0;
        }
        cpot[0] = 1;
        // 求M中每一列含非零元元素的个数
        for (t = 0; t < M.num; ++t) {
            ++num[M.data[t].j]; 
        }    
        // 求第col列中第一个非零元在T.data中的序号
        for (col = 1; col < M.columns; ++col) {
            cpot[col] = cpot[col - 1] + num[col - 1];
        }
        for (p = 0; p < M.num; ++p) {
            col = M.data[p].j;
            q = cpot[col];
            T.data[q].i = M.data[p].j;
            T.data[q].j = M.data[p].i;
            T.data[q].e = M.data[p].e;
            ++cpot[col];
        }
    }
}

TSMatrix S, T;

int main() {
    CreateSMatrix(S);
    FastTransposeSMatrix(S, T);
    PrintSMatrix(T);
}

Problem B 三元组顺序表表示的稀疏矩阵加法

题目

Problem B

7-2 三元组顺序表表示的稀疏矩阵加法

全屏浏览题目切换布局

作者 王东

单位 贵州师范学院

三元组顺序表表示的稀疏矩阵加法。

输入格式:

输入第1行为两个同型矩阵的行数m、列数n,矩阵A的非零元素个数t1,矩阵B的非零元素个数t2。
按行优先顺序依次输入矩阵A三元组数据,共t1行,每行3个数,分别表示非零元素的行标、列标和值。
按行优先顺序依次输入矩阵B三元组数据,共t2行,每行3个数,分别表示非零元素的行标、列标和值。

输出格式:

输出第1行为相加后矩阵行数m、列数n及非零元素个数t。
输出t行相加后的三元组顺序表结果,每行输出非零元素的行标、列标和值,每行数据之间用空格分隔。

输入样例1:
4 4 3 4
0 1 -5
1 3 1
2 2 1
0 1 3
1 3 -1
3 0 5
3 3 7
输出样例1:
4 4 4
0 1 -2
2 2 1
3 0 5
3 3 7

思路

使用三元组表示稀疏矩阵中的非零元素,进而创建一个三元组数组data[]来存储稀疏矩阵中的所有非零元素。对非零元素的坐标进行对比,如果坐标相同说明值要相加,否则直接赋值给矩阵Q。考虑到两个矩阵M和N的非零元素个数可能不相同,那么直接将剩余元素赋值给矩阵Q即可。输出时要注意忽略零元素。

代码

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

typedef int ElemType;
#define MAXSIZE 100 // 非零元个数的最大值

struct Triple
{
    int i, j;   // 行下标和列下标
    ElemType e; //非零元素值
};

struct TSMatrix
{
    Triple data[MAXSIZE + 1];   // 非零元三元组表,data[0]未用
    int rows, columns, num; // 矩阵行数、列数和非零元个数
};

/// @brief 用于比较c1和c2
/// @param c1 
/// @param c2 
/// @return 
int comp(int c1, int c2)
{                        
    if (c1 < c2)
        return 1;
    else if (c1 == c2)
        return 0;
    else
        return -1;
}

/// @brief 创建稀疏矩阵A, B
/// @param M
void CreateSMatrix(TSMatrix &A, TSMatrix &B)
{
    int i, m, n;
    ElemType e;
    scanf("%d %d %d %d", &A.rows, &A.columns, &A.num, &B.num);
    B.rows = A.rows;
    B.columns = B.columns;
    for (i = 0; i < A.num; ++i)
    {
        scanf("%d %d %d", &m, &n, &e);
        A.data[i].i = m;
        A.data[i].j = n;
        A.data[i].e = e;
    }
    for (i = 0; i < B.num; ++i)
    {
        scanf("%d %d %d", &m, &n, &e);
        B.data[i].i = m;
        B.data[i].j = n;
        B.data[i].e = e;
    }
}

/// @brief 求稀疏矩阵的和Q=M+N
/// @param M
/// @param N
/// @param Q
void AddSMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q)
{
    Triple *Mp, *Me, *Np, *Ne, *Qh, *Qe;
    Q.rows = M.rows;
    Q.columns = M.columns;
    Mp = &M.data[0];     // Mp的初值指向矩阵M的非零元素首地址
    Np = &N.data[0];     // Np的初值指向矩阵N的非零元素首地址
    Me = &M.data[M.num]; // Me指向矩阵M的非零元素尾地址
    Ne = &N.data[N.num]; // Ne指向矩阵N的非零元素尾地址
    Qh = Qe = Q.data;    // Qh、Qe的初值指向矩阵Q的非零元素首地址的前一地址
    while (Mp <= Me && Np <= Ne)
    {
        Qe++;
        switch (comp(Mp->i, Np->i))
        {
            case 1:
                *Qe = *Mp;
                Mp++;
                break;
            case 0:
                switch (comp(Mp->j, Np->j)) // M、N矩阵当前非零元素的行相等,继续比较列
                {
                    case 1:
                        *Qe = *Mp;
                        Mp++;
                        break;
                    case 0:
                        *Qe = *Mp;
                        Qe->e += Np->e;
                        if (!Qe->e) // 元素值为0,不存入压缩矩阵
                            Qe--;
                        Mp++;
                        Np++;
                        break;
                    case -1:
                        *Qe = *Np;
                        Np++;
                }
                break;
            case -1:
                *Qe = *Np;
                Np++;
        }
    }
    if (Mp > Me) // 矩阵M的元素全部处理完毕
        while (Np <= Ne)
        {
            Qe++;
            *Qe = *Np;
            Np++;
        }
    if (Np > Ne) // 矩阵N的元素全部处理完毕
        while (Mp <= Me)
        {
            Qe++;
            *Qe = *Mp;
            Mp++;
        }
    Q.num = Qe - Qh; // 矩阵Q的非零元素个数
}

/// @brief 输出稀疏矩阵M
/// @param M
void PrintSMatrix(TSMatrix M)
{
    int count = 0; // 计算零元素的个数,在输出时忽略之
    for (int ind = 1; ind <= M.num; ++ind)
    {
        if (M.data[ind].e == 0) {
            count++;
        }
    }
    printf("%d %d %d\n", M.rows, M.columns, M.num - count);
    for (int ind = 1; ind <= M.num; ++ind)
    {
        if (M.data[ind].e == 0)
        {
            continue;
        }
        printf("%d %d %d\n", M.data[ind].i, M.data[ind].j, M.data[ind].e);
    }
}

TSMatrix A, B, Q;

int main()
{
    CreateSMatrix(A, B);
    AddSMatrix(A, B, Q);
    PrintSMatrix(Q);
}

Problem C 串的模式匹配

题目

Problem C
Problem C

7-3 串的模式匹配

全屏浏览题目切换布局

作者 陈越

单位 浙江大学

给定两个由英文字母组成的字符串 String 和 Pattern,要求找到 Pattern 在 String 中第一次出现的位置,并将此位置后的 String 的子串输出。如果找不到,则输出“Not Found”。

本题旨在测试各种不同的匹配算法在各种数据情况下的表现。各组测试数据特点如下:

  • 数据0:小规模字符串,测试基本正确性;
  • 数据1:随机数据,String 长度为 105,Pattern 长度为 10;
  • 数据2:随机数据,String 长度为 105,Pattern 长度为 102;
  • 数据3:随机数据,String 长度为 105,Pattern 长度为 103;
  • 数据4:随机数据,String 长度为 105,Pattern 长度为 104;
  • 数据5:String 长度为 106,Pattern 长度为 105;测试尾字符不匹配的情形;
  • 数据6:String 长度为 106,Pattern 长度为 105;测试首字符不匹配的情形。
输入格式:

输入第一行给出 String,为由英文字母组成的、长度不超过 106 的字符串。第二行给出一个正整数 N(≤10),为待匹配的模式串的个数。随后 N 行,每行给出一个 Pattern,为由英文字母组成的、长度不超过 105 的字符串。每个字符串都非空,以回车结束。

输出格式:

对每个 Pattern,按照题面要求输出匹配结果。

输入样例:
abcabcabcabcacabxy
3
abcabcacab
cabcabcd
abcabcabcabcacabxyz
输出样例:
abcabcacabxy
Not Found
Not Found

思路

KMP算法,通过利用模式串pattern的信息,减少无效重复匹配的次数进而降低时间复杂度。

代码

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

typedef char SString;

/// @brief 求模式串T的next函数值并存入数组next
/// @param T 
/// @param next 
int* get_next(SString *T) {
    int len = strlen(T);
    int *next = (int *)malloc(sizeof(int) * len);
    int i = 0, j = -1;
    next[0] = -1;
    while (i < len - 1) {
        if (j == -1 || T[i] == T[j]) {
            ++i;
            ++j;
            next[i] = j;
        } else {
            j = next[j];
        }
    }
    return next;
} // get_next

/// @brief 利用模式串T的next函数求T在主串S中第pos个字符之后的位置的KMP算法
/// @param S 主串
/// @param T 模式串
/// @param pos 开始位置
/// @param next next数组
/// @return 第一次出现的位置
int Index_KMP(SString *S, SString *T, int *next) {
    int i = 0, j = 0;
    int lenS = strlen(S);
    int lenT = strlen(T);
    while (i < lenS && j < lenT) {
        // 继续比较后继字符
        if (j == -1 || S[i] == T[j]) {
            ++i;
            ++j;
        } else { // 匹配成功
            j = next[j];
        }
    }
    if (j == lenT) { // 匹配成功
        return i - lenT;
    } else {
        return -1;
    }
} // Index_KMP

/// @brief 输出S中index位置后的子串
/// @param S 
/// @param index 
void SubStrPrint(SString *S, int index) {
    int i = index;
    while (S[i]) {
        cout << S[i];
        i++;
    }
    printf("\n");
} // SubStrPrint

int main() {
    SString *S, *T;
    S = (SString *)malloc(sizeof(SString) * 1e6);
    T = (SString *)malloc(sizeof(SString) * 1e5);
    int num;
    cin >> S;
    cin >> num;
    for (int i = 1; i <= num; i++) {
        cin >> T;
        int *next = get_next(T);
        int index = Index_KMP(S, T, next);
        if (index == -1) {
            cout << "Not Found" << endl;
        } else {
            SubStrPrint(S, index);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值