数据结构学习笔记

# 没有书本,就把数据结构的记录mark在这个地方

 2020/03/23


顺序存储和随机存储是两种物理存储结构。其并列的是索引存储和散列存储

👉线性表的顺序存储结构是一种随机存取 的存储结构,线性表的链式存储结构是一种() 的存储结构。

顺序存取,随机存取是指对于存储在物理存储结构种的数据的访问读写方式

顺序存取:数据只可以按照顺序来依次存取

随机存取:数据可以不需要按照顺序来随机存取

顺序线性表可以随机存取

链式线性表可以顺序存取

为了弥补上述两个表的缺陷,建立静态/动态链表(用顺序表实现链表)的方式 。

静态链表存储数据      备用链表和数据链表   建立好的静态链表

图自👉静态链表

备用表头一般在物理地址首位,每一次添加删除,都需要对表头的次下标做修改。

数据链表表尾的次下标(游标)是0,即备用表头

一个数据组需要,增删改查。静态链表整体还是类似链表,删时,不需要大动干戈。

删时,将数据表被删除项游标赋值给前一项游标,再回收空间

备用链表和数据链表的存储空间依旧受到初次分配的影响

静态链表在创建时已经申请分配了空间(有限),动态链表则在使用时才申请分配空间(无限)


图自👉堆、栈、程序区、静态数据区、字符常量区的介绍与区别

Brute Force BF算法(所谓的暴力解法?) 

KMF算法(跳过方法)

 

20200326


数组在内存中的存储方式👉图自数组的顺序存储及(C语言)实现

以列序为主:

以行序为主:

查找方式

如果二维数组采用以行序为主的方式,则在二维数组 a_nm 中查找 a_ij 存放位置的公式为:

LOC(i,j) = LOC(0,0) + (i*m + j) * L;

 

20200327


下转自👉矩阵乘法

十字链表 = 三元组链表 + 域表头数组

遍历获得的三元表是有序的(以先行后列为例)

一次循环中:

1)对于行插入非零数字,如果列序大于链内数据,则在最右append;如果小于,则在表头append

2)对于列插入非零数字,如果行序大于~~~

行逻辑链接的顺序表解决矩阵乘积算法

对矩阵的乘积进行深度剖析,矩阵 A 和矩阵 B 相乘的运算过程是这样的:
 
  1. 首先,找到矩阵 A 中第一行的非 0 元素,分别是 A11 = 3和 A14 = 5;(由于行逻辑链接的顺序表中存储的都是非 0 元素,查找的过程就需要使用记录每行第一个非 0 元素的首地址的数组来完成)
  2. 用 3 去和 B 中对应的第一行中的非 0 元素相乘,矩阵 B 中第一行非 0 元素是 B12 = 2,所以 3*2 = 6 ,因为 6 是 A11 和 B12 相乘的结果,所以暂时存放在 C12 中;用 5 去和 B 中对应的第 4 行的非 0 元素相乘,由于矩阵 B 中第 4 行没有非 0 元素,所以,第一行的计算结束;(相加
  3. 以此类推。

无论如何使用三种存储形式做加法,三元表的行内列内顺序都是一致的(递增)

使用十字链表来解决加法问题:

1)如果A中非零位置,B中为零,则A不变

2)如果A中非零元素,B中非零,且和为非零,直接在A中叠加(为零则删除)

3)如果A中零位置,B中为非零,则将B位置元素append入A

4)如果都为零,则不变

广义表

可以存储表的表 (数组只能存储不可再分的数据类型)

原子和子表

通常,广义表中存储的单个元素称为 "原子",而存储的广义表称为 "子表"。

例如创建一个广义表 LS = {1,{1,2,3}},我们可以这样解释此广义表的构成:广义表 LS 存储了一个原子 1 和子表 {1,2,3}。

以下是广义表存储数据的一些常用形式:

  • A = ():A 表示一个广义表,只不过表是空的。
  • B = (e):广义表 B 中只有一个原子 e。
  • C = (a,(b,c,d)) :广义表 C 中有两个元素,原子 a 和子表 (b,c,d)。
  • D = (A,B,C):广义表 D 中存有 3 个子表,分别是A、B和C。这种表示方式等同于 D = ((),(e),(b,c,d)) 。
  • E = (a,E):广义表 E 中有两个元素,原子 a 和它本身。这是一个递归广义表,等同于:E = (a,(a,(a,…)))。


注意,A = () 和 A = (()) 是不一样的。前者是空表,而后者是包含一个子表的广义表,只不过这个子表是空表。

 union关键字,定义union下面的成员变量共享一块内存,每一个成员在任一时刻有且只有一个成员使用此块内存。

广义表 {a,{b,c,d}} 的结构示意图        广义表节点的两种类型

NOTE:节点必须被表节点引领

typedef struct GLNode{
    int tag;//标志域
    union{
        char atom;//原子结点的值域
        struct{
            struct GLNode * hp,*tp;
        }ptr;//子表结点的指针域,hp指向该子表的表头;tp指向该子表的表尾
    };
}*Glist;

广义表 {a,{b,c,d}} 的存储结构示意图   广义表的另一套节点结构

NOTE:表节点相当于{ }

typedef struct GLNode{
    int tag;//标志域
    union{
        int atom;//原子结点的值域
        struct GLNode *hp;//子表结点的指针域,hp指向表头
    };
    struct GLNode * tp;//这里的tp相当于链表的next指针,用于指向下一个数据元素
}*Glist;

广义表的另一套节点结构

 

20200330


所谓队列,就是有从队头弹出,队尾压入的。

起初队尾和队头重合,弹出后队头向后移动,压入前队尾向前移动。

无论是什么结构的队列,当队头和队尾重合的时候,则队列要么已满无法写入,要么就不存在元素了。

链式队列有一个专用的空队头,所以弹出不用移动指针。

👉广义表长度深度

广义表长度,第一层所含的元素

广义表深度,相当于不确定分叉的n叉树深度

停止条件:(每次只记录最大值

当为原子时返回0,再前一次中+1

当为空表时返回1

for 把每个表中元素遍历一遍

int GlistDepth(Glist C){
    //如果表C为空表时,直接返回长度1;
    if (!C) {
        return 1;
    }
    //如果表C为原子时,直接返回0;
    if (C->tag==0) {
        return 0;
    }
    int max=0;//设置表C的初始长度为0;
    for (Glist pp=C; pp; pp=pp->ptr.tp) {
        int dep=GlistDepth(pp->ptr.hp);
        if (dep>max) {
            max=dep;//每次找到表中遍历到深度最大的表,并用max记录
        }
    }
    //程序运行至此处,表明广义表不是空表,由于原子返回的是0,而实际长度是1,所以,此处要+1;
    return max+1;
}

表头!指的是表的第一个元素。

表尾!指的时表的第一个元素之后的组成的表。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值