数据结构(C/C++)专题一:顺序表与链表

今天开始一个新的专题:数据结构当然,不仅仅适用于学习也适用于408考研。

那么提起数据结构

思维导图:总结如下:·

1.初识顺序表与链表

首先呢我们要明白,数据结构有物理结构,也有逻辑结构

物理结构

就是电脑实际的结构,链式,非链式,索引,散列

eg:

链式结构(Linked Structure)

例子:火车车厢

想象一列火车,每节车厢都连接在一起。每一节车厢(数据节点)都有一个链接(指针),连接到下一节车厢。这就是链式结构。要找到某一节车厢,你需要从第一节车厢开始,依次通过连接找到目标车厢。

非链式结构(Non-Linked Structure)

例子:书架

现在想象一个书架,上面整齐地排列着书籍。每本书(数据项)都直接放在一个固定的位置。你可以通过书的位置直接找到它,而不需要从第一本书开始逐本寻找。这就是非链式结构。

索引(Index)

例子:图书馆的目录卡片

想象一个图书馆,每本书在书架上的位置都通过一张目录卡片来记录。你可以先查找目录卡片(索引),找到书的位置,然后直接去拿书。这种方法提高了查找效率,因为你不需要在书架上一本本地找。

散列(Hashing)

**例子:钥匙和钥匙扣】

想象你有一个钥匙扣,上面挂着多把钥匙。每把钥匙上都有一个标签(哈希值),标明它对应的锁(数据位置)。当你要找某一把钥匙时,你通过钥匙上的标签很快就能找到它。这就是散列的基本原理,通过一个哈希函数(标签生成方式),可以快速找到数据的位置。

逻辑结构

简单讲就是脑子里面想的,分为线性与非线性

线性结构(Linear Structure) 例子:排队买票

想象你在电影院排队买票。大家一个接一个排成一条直线,这就是线性结构。每个人的位置是有序的,前面有一个人,后面也有一个人(除了队首和队尾)。

实际数据结构:数组和链表

  • 数组:就像排队,每个人(元素)都有固定的位置(索引)。你可以通过位置(索引)快速找到任何一个人(元素)。
  • 链表:也是线性结构,但每个人(节点)手里都有一个纸条,写着下一个人的名字(指针)。你要找到某个人,需要从第一个人开始,一个个问过去。
  • 栈(Stack)

    例子:书堆

    想象一堆书,你只能从顶部添加或移除书。这就是栈的概念。栈是一种“后进先出”(Last In, First Out, LIFO)的结构。最新放进去的元素最先被取出来。

    实际数据结构:栈

  • 操作
    • 压栈(Push):在栈顶添加一个元素。
    • 出栈(Pop):从栈顶移除一个元素。
    • 栈顶(Top/Peek):查看栈顶的元素而不移除它。
  • 队列(Queue)

    例子:排队买票

    想象在电影院排队买票,最早来的人最先买到票,最晚来的人最后买到票。这就是队列的概念。队列是一种“先进先出”(First In, First Out, FIFO)的结构。最先进入队列的元素最先被取出。

    实际数据结构:队列

  • 操作
    • 入队(Enqueue):在队尾添加一个元素。
    • 出队(Dequeue):从队首移除一个元素。
    • 队首(Front):查看队首的元素而不移除它。

非线性结构(Non-Linear Structure) 例子:家谱图

想象一个家谱图,它展示了一个家族的成员关系。祖先在上,后代在下,分支可能有很多。这就是非线性结构。每个人(节点)可以有多个孩子(指向多个节点)。

实际数据结构:树和图

  • :就像家谱图,每个节点可以有多个子节点(孩子),但只有一个父节点(除了根节点)。例如,二叉树是一种特殊的树,每个节点最多有两个子节点。
  • :比家谱图更复杂,每个节点可以和多个节点有连接(边)。例如,城市地图就是一个图结构,城市是节点,道路是边。

总结如下:

408常考题目:判断是逻辑还是物理结构.

技巧:指数据元素之间的逻辑关系,与数据的存储无关,独立于计算机的用于判断逻辑。

注意:哈希表是物理结构,与存储结构有关,循环队列也是。

关于站和队列,则是逻辑结构。

2.顺序表

开始线性表的学习了。

导图:

什么是顺序表呢?

类似于数组;

  • 静态分配

    • 类型定义

      typedef struct {
          ElemType data[MaxSize];
          int length;
      } SqList;
      

    • typedef struct {...} SqList;

      • 这段代码定义了一个结构体,并通过 typedef 给它起了一个别名 SqList。这样你可以使用 SqList 来声明这种结构体类型的变量,而不需要每次都写 struct {...}
    • ElemType data[MaxSize];

      • data 是一个数组,它的类型是 ElemType,数组的大小是 MaxSize
      • ElemType 是一个占位符,通常在实际代码中会被替换为具体的数据类型,例如 intfloat 或者自定义的数据类型。
      • MaxSize 是一个宏定义或常量,表示顺序表可以容纳的最大元素数量。
    • int length;

      • length 用来记录顺序表当前的长度,即顺序表中实际包含的元素个数。
  • 动态分配(好好讲讲)

struct SqList {
    ElemType* data;  // 指向动态分配数组的指针
    int length;      // 当前顺序表的长度
    int maxSize;     // 顺序表的最大容量
};

注意:这个可和链表不一样 注意:动态分配不是链式存储,它同样属于顺序存储结构,物理结构没有变化,只是分配的空间大小可以在运行时动态决定

具体用法:

1.初始化顺序表

// 构造函数,初始化顺序表

SqList(int maxSize) : maxSize(maxSize), length(0)

{

data = new ElemType[maxSize];

}

2.增加 

// 增加元素到顺序表尾部

void insertElem(ElemType elem)

{ if (length >= maxSize)

{

throw std::overflow_error("顺序表已满,无法插入元素。");

}

data[length] = elem;

length++; }

 // 在指定位置插入元素
    void insertElemAt(int pos, ElemType elem) {
        if (pos < 0 || pos > length) { // 注意:这里 pos 可以等于 length,表示在末尾插入
            throw std::out_of_range("位置非法,无法插入元素。");
        }
        if (length >= maxSize) {
            throw std::overflow_error("顺序表已满,无法插入元素。");
        }
        for (int i = length; i > pos; i--) {
            data[i] = data[i - 1];
        }
        data[pos] = elem;
        length++;
    }

408里面  长度为n

  • 注意:线性表元素序号从1开始(逻辑位序和物理位序相差1)

    • 合法插入位置:1 <= i <= n+1(表尾)

代码改为:  void insertElemAt(int pos, ElemType elem) {
        if (pos < 1 || pos > length + 1) { // 合法位置范围为 1 <= pos <= length + 1
            throw std::out_of_range("位置非法,无法插入元素。");
        }
        if (length >= maxSize) {
            throw std::overflow_error("顺序表已满,无法插入元素。");
        }
        for (int i = length; i >= pos; i--) {
            data[i] = data[i - 1];
        }
        data[pos - 1] = elem; // 将位置 pos 转换为索引 pos-1
        length++;

    }

3.删除

  // 删除顺序表中指定位置的元素
    void deleteElem(int pos) {
        if (pos < 0 || pos >= length) {
            throw std::out_of_range("位置非法,无法删除元素。");
        }
        for (int i = pos; i < length - 1; i++) {
            data[i] = data[i + 1];
        }
        length--;
    }
 

408里面 长度为n

  • 注意:合法删除位置:1 <= i <= n

  • 为了符合删除操作的合法位置约束(1 <= i <= n),需要对删除元素的位置进行适当的调整。C++ 中数组的索引从 0 开始,但在实际使用中,位置可能从 1 开始,因此需要进行相应的转换。在 C++ 实现中,我们需要对位置参数进行减1操作,以使其适应 C++ 中的数组索引。

  • void deleteElem(int pos) {

  •         if (pos < 1 || pos > length) { // 合法位置范围为 1 <= pos <= length
                throw std::out_of_range("位置非法,无法删除元素。");
            }
            for (int i = pos - 1; i < length - 1; i++) {
                data[i] = data[i + 1];
            }
            length--;
        }

4.修改

// 修改顺序表中指定位置的元素
    void updateElem(int pos, ElemType newElem) {
        if (pos < 0 || pos >= le

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lidiyscrp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值