【数据结构】线性表_复习笔记总结

一、顺序存储

  • 简单理解就是用结构体存着的数组

1. 结构体定义

typedef int Position;
typedef struct LNode * PtrToLNode;
struct LNode
{
    ElmenetType Data[ MAXSIZE ]; // 存储数据信息
    Position Last; // 存储线性表最后一个元素的位置
};
typedef PtrToLNode List;

2. 初始化空表

List MakeEmpty()
{
    List PtrL; // 定义线性表的头结点
    PtrL = (List )malloc(sizeof(struct LNode)); // 为整个线性表分配空间
    PtrL->Last = -1; // 此时线性表为空,最后一个元素指向-1
    return PtrL; // 返回头结点
}

3. 查找元素

在线性表 PtrL 中查找给定元素 X

思路: 遍历整个线性表,找到就返回 X 所在位置 i ,找不到就返回 -1

int Find(ElementType X, List PtrL)
{
    int i = 0;
    // 从第一个元素遍历到最后一个元素,若数值等于X就跳出
    while (i <= PtrL->Last && PtrL->Data[i] != X ) i ++;
    if (i > PtrL->Last ) return -1; // 线性表中没有X,返回-1
    else return i;
}

4. 插入元素

将给定元素 X 插入到线性表 PtrL 的第 i 个位置

思路: 线性表从后往前,把第 i 个位置到最后一个位置(也就是 Last - 1 的位置)的数全往后挪一个,目的是把第 i 个位置腾出来放新插入的元素,最后记得让Last ++

  • 关于为什么从后往前呢? 因为从后往前挪才能保证每个元素都没有丢失,从前往后挪,前一个元素会把后一个元素的值覆盖掉
void Insert(ElementType X, int i, List PtrL )
{
    int j;
    if (PtrL->Last == MAXSIZE - 1) // 此时表示线性表存满,不能插入元素
    {
        cout << "FULL.";
        return;
    }
    if (i < 1 || i > PtrL->Last + 2) // 此时给定的位置 i 不合法
    {
        cout << "The location is not legal.";
        return;
    }
    for (j = PtrL->Last; j >= i - 1; j -- ) // 第i个元素其实是在数列中的第i-1啦
        PtrL->Data[j + 1] = PtrL->Data[j];
    PtrL->Data[i - 1] = X; // 挪完之后赋值
    PtrL->Last ++; // 不要忘了把线性表最后一个元素的位置也往后挪一个
    return;
}

5. 删除元素

删除线性表 PtrL 中第 i 个元素

思路: 线性表从前往后,把从第 i + 1 个元素开始到最后一个元素全部往前挪一位,覆盖掉第 i 个位置的元素,相当于删掉了第 i 个元素

  • 为什么不从后往前挪的原因和上面那条一样
void Delete(int i, List PtrL)
{
    int j;
    if (i < 1 || i > PtrL->Last + 1) // 此时给定的位置 i 不合法
    {
        cout << "The location is not legal.";
        return;
    }
    for (j = i; j <= PtrL->Last; j ++ )
        PtrL->Data[j - 1] = PtrL->Data[j];
    PtrL->Last -- ; // 挪完不要忘了把最后一个元素的位置也往前挪一个
    return;
}

二、链式存储

  • 简单理解就是把每个数据分别存在一个方块里,然后用线(也就是指针)把这些方块串起来

1. 结构体定义

typedef struct LNode *List;
struct LNode{
    ElementType Data; // 存这个方块里的数
    List Next; // 这个指针存的是下一个方块的位置
};

2. 求表长

思路: 就是很简单的遍历一遍…

int Length(List PtrL)
{
    List p = PtrL; // p在表头位置
    int j = 0; // 表长初始化为0
    while (p) // 只要p不为NULL就继续循环
    {
        p = p->Next;
        j ++; // 表长++
    }
    return j;
}

3. 查找元素

思路: 很显然就是遍历单链表

(1)查找指定的数值 X

List Find(ElementType X, List PtrL)
{
    List p = PtrL; // p指向表头
    while (p != NULL && p->Data != X)
        p = p->Next;
    return p; // 找到了就会返回X所在的指针,没找到正好会返回NULL
}

(2)查找指定的位置 K

List FindKth(int K, List PtrL)
{
    List p = PtrL; // p指向表头
    int i = 1; // 表示目前正在遍历第 i 个位置
    while (p != NULL && i < K)
    {
        p = p->Next;
        i ++;
    }
    if (i == K) return p; // 找到返回该位置的指针
    else return NULL; // 找不到返回NULL
}

4. 插入元素

在线性表 PtrL 中插入元素 X 到第 i 个位置

思路: 先找到要插入位置的前一个位置(也就是第 i - 1 个位置),把这个新结点的 Next 指针指向前一个结点的 Next ,然后再将前一个结点的 Next 指向这个新结点,就完成啦~
单链表插入操作

List Insert(ElementType X, int i, List PtrL)
{
    List p, s;
    if (i == 1) // 如果要在第一个位置插入
    {
        s = (List)malloc(sizeof(struct LNode));
        s->Data = X;
        s->Next = PtrL; // 让这个新结点指向头结点就好啦
        return s; // 这个新结点变成新的头结点,返回
    }
    p = FindKth(i - 1, PtrL); // 如果不是第一个结点,先找到前一个结点,用p指向前一个结点
    if (p == NULL) // 前一个结点不存在
    {
        cout << "Illegal.";
        return NULL;
    }
    else
    {
        s = (List)malloc(sizeof(struct LNode));
        s->Data = X;
        s->Next = p->Next;
        p->Next = s;
        return PtrL;
    }
}

5. 删除元素

在线性表 PtrL 中插入第 i 个元素

思路: 找到被删除元素的前一个位置,让前一个位置的 Next 指向被删除元素的 Next ,释放掉被删除元素,完成~
单链表删除操作

List Delete(int i, List PtrL)
{
    List p, s;
    if (i == 1) // 删除的是第一个元素
    {
        s = PtrL; // s指向单链表第一个位置
        if (PtrL != NULL) PtrL = PtrL->Next; // 表不为空,就让PtrL指向下一个作为头结点
        else return NULL; // 表为空,没法删去
        free(s); // 释放s的内存
        return PtrL;
    }
    p = FindKth(i - 1, PtrL); // 找到被删除元素的前一个位置,赋为p
    if (p == NULL) // 前一个位置不存在
    {
        cout << "Illegal.";
        return NULL;
    }
    else if(p->Next == NULL) // 删除的位置不存在
    {
        cout << "Illegal.";
        return NULL; 
    }
    else
    {
        s = p->Next; // s指向被删除元素
        p->Next = s->Next;
        free(s);
        return PtrL;
    }
}

三、 顺序存储和链式存储的比较

  • 顺序存储
    • 需要完整连续的一片空间存储
    • 可以在 O(1) 的时间复杂度内访问查找
    • 插入删除效率低
    • 大小固定,不能随意拓展
  • 链式存储
    • 内存利用率高,不需要连续的空间存储
    • 查找访问效率低,需要从表头开始遍历
    • 插入删除方便
    • 大小不固定,可以随意拓展
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Texcavator

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

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

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

打赏作者

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

抵扣说明:

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

余额充值