• 7.0、C语言数据结构——线性表 (2)


    7.0、C语言数据结构——线性表 (3)

            我们先来看下单来链表的插入,假设存储元素 e 的结点为 s ,要实现结点 p ,p -> next 和 s 之间逻辑关系的变化,大家参考下图思考一下:

            1. 我们思考后发觉根本用不着惊动其他结点,只需要让 s -> next 和 p -> next 的指针做一点改变; 
            s -> next = p -> next;
            p -> next = s;
            2. 我们通过图片来解读一下这两句代码 ->

    单链表数据插入的总结如下:

            1.声明一结点 p 指向链表头结点,初始化 j 从 1 开始;
            2. 当 j < 1 时,就遍历链表,让 p 的指针向后移动,不断指向下一结点,j 累加 1;
            3. 若到链表末尾 p 为空,则说明第 i 个元素不存在;
            4. 否则查找成功,在系统中生成一个空结点 s;
            5. 将数据元素 e 赋值给 s -> data;
            6. 单链表的插入刚才两个标准语句;
            7. 返回成功;

    1. Status ListInsert (LinkList* L , int i , ElemType e) {
    2. int j;
    3. LinkList p , s;
    4. p = *L;
    5. j = 1;
    6. while() {
    7. p = p -> next;
    8. j++;
    9. }
    10. if(!p || j > i) {
    11. return ERROR;
    12. }
    13. s = (LinkList)malloc(sizeof(Node));
    14. s -> data = e;
    15. s -> next = p -> next;
    16. p -> next = s;
    17. return OK;
    18. }

    单链表删除操作:

            1. 假设元素 a2 的结点为 q ,要实现结点 q 删除单链表的操作,其实就是将它的前驱结点的指针绕过指向后继结点即可;
            2. 那我们所要做的,实际上就是一步:
            可以这样: p -> next = p -> next -> next;
            也可以是:q = p -> next;p -> next = q -> next;
     

    单链表第 i 个数据删除结点的算法思路:

            1. 声明结点 p 指向链表第一个结点,初始化 j = 1;
            2. 当 j < 1 时,就遍历链表,让 p 的指针向后移动,不断指向下一结点,j 累加 1;
            3. 若到链表末尾 p 为空,则说明第 i 个元素不存在;
            5.否则查找成功,将欲删除结点 p -> next 赋值给 q ;
            6. 单链表的删除标准语句 p -> next = q -> next;
            7. 将 q 结点中的数据赋值给 e ,作为返回;
            8. 释放q 结点;

    1. Status ListDelete (LinkList* L , int i , ElemType* e) {
    2. int j;
    3. LinkList p , q;
    4. p = *L;
    5. j = 1;
    6. while(p->next && j < i) {
    7. p = p -> next;
    8. ++j;
    9. }
    10. if(!(p -> next) || j > i) {
    11. return ERROR;
    12. }
    13. q = p -> next;
    14. p -> next = q -> next;
    15. *e = q -> data;
    16. free(q);
    17. return OK;
    18. }

    最后单链表和顺序存储效率比较一下得出结论:

            1. 我们最后的环节是效率 PK ,我们发现无论是单链表插入还是删除算法,他们其实都是由两个部分组成:第一部分就是遍历查找第 i 个元素,第二部分就是实现插入和删除元素;
            2.从整个算法来说,我们很容易可以推出他们的时间复杂度都是 O ( n );
            3. 再详细点分析:如果在我们不知道第 i 个元素的指针位置,单链表数据结构在插入和删除操作上,与线性表的顺序存储结构是没有太大优势的;
            4. 但如果,我们希望从第 i 个位置开始,插入连续 10 个元素,对于顺序存储结构意味着,每一次插入都需要移动 n - i 个位置,所以每次都是 O ( n );
            5. 而单链表,我们只需要在第一次时,找到第 i 个位置的指针,此时为 O ( n ),接下来只是简单地通过赋值移动指针而已,时间复杂度都是 O ( 1 );
            6. 显然,对于插入或删除数据越频繁的操作,单链表的效率优势就越明显;

  • 相关阅读:
    使用kubenetes dashboard控制台部署项目
    LINMP搭建wordpress-数据库不分离
    1、JVM:什么是JVM?
    计算机视觉:一文搞懂卷积神经网络中的池化层
    一次直播和图像识别技术应用的探索之旅
    FFplay文档解读-15-重采样器选项,缩放选项,过滤简介,graph2dot,滤波器描述,时间表编辑,具有多个输入的过滤器选项(帧同步)
    celery笔记七之周期/定时任务及crontab定义
    Flutter 直接调用so动态库,或调用C/C++源文件内函数
    类的成员之二:方法(method)
    Day 62 django form modelform组件
  • 原文地址:https://blog.csdn.net/m0_52433668/article/details/126922966