【数据结构】第四章——字符串和多维数组(详解)

前言:
本系列是笔者暑假自学数据结构的笔记整理而来,共126页,3w+字。现在正式开学上课,补充老师所讲内容,并且仔细勘误,根据老师的教学进度分章节发布在CSDN上。

教材使用的是王红梅等所著的数据结构——从概念到C++实现(第三版)。
暑假自学时期主要参考的网课:
青岛大学-王卓
武汉大学-李春葆

定义与概念

串(或字符串)是由零个或多个字符组成的有限序列。

基本运算

/*
    StrAssign(&s, cstr):将字符串常量cstr赋值给串s,即生成其值等于cstr的串s
    StrCopy(&s, t):串复制,将串t赋值给串s
    StrEqual(s, t):判断串是否相等,若相等返回真,若不等返回假
    StrLength(s):求串长,返回串s中的字符个数
    Concat(s, t):串连接,返回由串s和串t连接在一起的新串
    SubStr(s, i, j):求子串,返回串s中从第i个字符开始的连续的j个字符组成的子串
    InsStr(s1, i, s2):插入,将串s2插入到串s1的第i个字符中,返回新串
    DelStr(s, i, j):删除,从串s中删去从第i个字符开始的长度为j的子串,并返回产生的新串
    RepStr(s, i, j, t):替换,在串s中,将第i个字符开始的连续的j个字符构成的子串用串t替换,并返回新串
    DispStr(s):串输出,输出串s的所有值
*/

类似的,串可分为两类—顺序串和链串。而串的顺序存储又有两种方法:1.每个单元(例如4字节)只存一个字符,称为非紧缩格式,其存储密度小。2.每个单元存放多个字符,称为紧缩格式,其存储密度大。我们一般讨论前者。

//对于非紧缩格式的字符串,类型定义如下
#define MAXSIZE 100
typedef struct 
{
    char data[MAXSIZE];
    int length;//字符串长度
}SqString;

顺序串中实现串的基本运算与顺序表的基本运算类似,详细算法见教材。
Eg:
实现Strcmp(s1, s2):

int Strcmo(SqString s, SqString t)
{
    int i, len;
    len = s.length <= t.length?s.length:t.length;
    for (i = 0; i < len; i++)
    {
        return (s.data[i]>t.data[i]) && (s.data[i] != t.data[i])?1:-1;
    }
    if (s.length == t.length)
    {
        return 0;
    }
    else
    {
        return s.length > t.length?1:-1;
    }
}

链串的组织形式与一般的链表类似。
链串中的一个节点可以存储多个字符。通常将链串中每个节点所存储的字符个数称为节
点大小,链串不一定只能采用单链表,要依据情况而定。如果需要从某个节点出发前后查找,可以采用双链表,如果需要快速查找尾结点,可以采用循环双链表。
我们一般只考虑节点大小为1的链串,定义如下:

typedef struct snode
{
    char data;
    struct snode *next;
}LiString;

同样的,链串中实现串的基本运算与单链表的基本运算类似,详细算法见教材。

串的模式匹配

这部分内容请参看我的另一篇文章:
【数据结构】串模式匹配及KMP算法详解——看不懂来砍我

一些习题
1.str=”Software”,其子串个数?
解:如果原串没有重复元素,那么子串共n(n+1)/2+1

数组

定义与概念

在这里插入图片描述
优先存储压缩
在这里插入图片描述
一个习题:
若将n阶上三角矩阵A按列优先顺序存储压缩存放在一维数组B[1…n(n+1)/2]中,A中第一个非零元素a11 存放于B数组的b1中,则应存放到bk中的非零元素aij的下标i、j与k的对应关系是?

解:1~j-1列的元素个数是:j(j-1)/2,第j列aij之前的元素个数:i-1,故k= j(j-1)/2+ i-1 +1 =
j(j-1)/2+i。

稀疏矩阵

一个阶数较大的矩阵中的非零元素个数s相对于矩阵元素的总个数t十分小,即s<<t时,称该矩阵为稀疏矩阵。
稀疏矩阵的压缩存储办法是只存储非零元素,稀疏矩阵中的每一个非零元素需由一个三元组
在这里插入图片描述
唯一确定,稀疏矩阵中的左右非零元素构成三元组线性表。

基本运算

#define MAXSIZE 100
#define ElemType int
typedef struct 
{
    int r;//行号
    int c;//列号
    ElemType d;//元素值
}TupNode;//三元组定义
typedef struct 
{
    int rows;//行数值
    int cols;//列数值
    int nums;//非零元素个数
    TupNode data[MAXSIZE];
}TsMatrix;//三元组顺序表定义

void CreateMat(TsMatrix &t, ElemType A[M][N])
{
    int i, j;
    t.rows = M;
    t.cols = N;
    t.nums = 0;
    for (i = 0; i < M; i++)
    {
        for (j = 0; j < N; j++)
        {
            if (A[i][j] != 0)
            {
                t.data[t.nums].r = i;
                t.data[t.nums].c = j;
                t.data[t.nums].d = A[i][j];
                t.nums++;
            }
        }
    }
}

//在下标为i,j的位置赋值为x
bool Value(TsMatrix &t, ElemType x, int i, int j)
{
    int k = 0, k1;
    if (i >= t.rows || j >= t.cols)
    {
        return false;//ij违法返回false
    }
    while (k < t.nums && i > t.data[k].r)//查找行
    {
        k++;
    }
    while (k < t.nums && i == t.data[k].r && j > t.data[k].c)//查找列
    {
        k++;
    }
    if (t.data[k].r == i && t.data[k].c == j)//找到了
    {
        t.data[k].d = x;
    }
    else//不存在就插入一个元素
    {
        for (k1 = t.nums - 1; k1 >= k; k1--)
        {
            t.data[k1 + 1].r = t.data[k1].r;
            t.data[k1 + 1].c = t.data[k1].c;
            t.data[k1 + 1].d = t.data[k1].d;
        }
        t.data[k].r = i;
        t.data[k].c = j;
        t.data[k].d = x;
        t.nums++;
    }
    return true;
}
//将指定的元素值赋给变量
bool Assign(TsMatrix t, ElemType &x, int i, int j)
{
    int k = 0;
    if (i >= t.rows || j >= t.cols)
    {
        return false;
    }
    while (k < t.nums && i > t.data[k].r)//查找行
    {
        k++;
    }
    while (k < t.nums && i == t.data[k].r && j > t.data[k].c)//查找列
    {
        k++;
    }
    if (t.data[k].r == i && t.data[k].c == j)//找到了
    {
        x = t.data[k].d;
    }
    else//没找到,就置x为0
    {
        x = 0;
    }
    return true;
}
//输出三元组
void DispMat(TsMatrix t)
{
    if (t.nums <= 0)
    {
        return;
    }
    cout << "\t" << t.rows << "\t" << t.cols << "\t" << t.nums;
    cout << "-------------------------------------------";
    for (int i = 0; i < t.nums; i++)
    {
         cout << "\t" << t.data[i].r << "\t" << t.data[i].c << "\t" << t.data[i].d;
    }
}
//矩阵转置,一种非高效算法
//m行n列,t个非0元素,时间复杂度为O(nt)
void TranTat(TsMatrix t, TsMatrix &tb)
{
    int p, q = 0, v;//q为tb.data的下标
    tb.rows = t.cols;
    tb.cols = t.rows;
    tb.nums = t.nums;
    if (t.nums != 0)//当存在非零元素时执行转置
    {
        for (v = 0; v < t.cols; v++)//tb.data[q]中记录以列序排列
        {
            for (p = 0; p < t.nums; p++)//p为t.data的下标
            {
                if (t.data[p].c == v)
                {
                    tb.data[q].r = t.data[p].c;
                    tb.data[q].c = t.data[p].r;
                    tb.data[q].d = t.data[p].d;
                    q++;
                }
            }
        }
    }
}

十字链表

在这里插入图片描述
特殊矩阵压缩存储后仍具有随机存取特性,但一个稀疏矩阵采用压缩后,和直接采用二维数组存储相比会失去随机存取特性。

广义表

在这里插入图片描述

以上 如果此篇博客对您有帮助欢迎点赞与转发 有疑问请留言或私信 2020/10/3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值