数据结构 1-2 线性表的链式存储-链表

1 原理

顺序表的缺点:

  • 插入和删除移动大量元素
  • 数组的大小不好控制
  • 占用一大段连续的存储空间,造成很多碎片

链表规避了上述顺序表缺点

逻辑上相邻的两个元素在物理位置上不相邻

头结点

L:头指针

头指针:链表中第一个结点的存储位置,用来标识单链表。

头结点:在单链表第一个结点之前附加的一个结点,为了操作上的方便。

若链表有头结点,则头指针永远指向头结点,不论链表是否为空,头指针均不为空,头指针是链表的必须元素,他标识一个链表。头结点是为了操作的方便而设立的,其数据域一般为空,或者存放链表的长度。有头结点后,对在第一结点前插入和删除第一结点的操作就统一了,不需要频繁 重置头指针。但头结点不是必须的。

优缺点

优点:

  • 插入和删除操作不需要移动元素,只需要修改指针
  • 不需要大量的连续存储空间

缺点:

  • 单链表附加指针域,也存在浪费存储空间的缺点
  • 查找操作时需要从表头开始遍历,依次查找,不能随机存取

2 表示

2.1 定义

cpp 复制代码
typedef int ElemType ;

typedef struct LNode{ //单链表结点类型
    ElemType  data; //数据域
    struct LNode* next;//指针域
}LNode, *LinkList;

2.2 新建链表

2.2.1 头插法新建链表
cpp 复制代码
void list_head_insert(LinkList &L)
{
    ElemType x;
    LNode *s;
    L= (LinkList)malloc(sizeof(LNode));//申请头节点空间
    L->next = NULL;
    scanf("%d",&x);

    while(x!=9999)
    {
        s= (LinkList)malloc(sizeof(LNode));//申请节点空间
        s->data = x;
        s->next = L->next;//指向原本第一个节点
        L->next = s; //头结点的next
        scanf("%d",&x);
    }
}
2.2.2 尾插法新建链表
cpp 复制代码
void list_tail_insert(LinkList &L)
{
    L= (LinkList)malloc(sizeof(LNode));//申请头节点空间
    ElemType x;
    LNode *s, *r = L;//s是用来指向新节点,r始终指向链表尾部
    L->next = NULL;
    scanf("%d", &x);
    while(x!=9999)
    {
        s = (LinkList) malloc(sizeof(LNode));
        s->data=x;
        r->next = s;
        r=s;
        scanf("%d", &x);
    }
    r->next=NULL;//让为节点的next=NULL

}

2.3 打印链表

cpp 复制代码
void print_list(LinkList L)
{
    L = L->next;
    while(L != NULL)
    {
        printf("%3d",L->data);
        L =L->next;
    }
    printf("\n");
}

2.4 查找

2.4.1 按位置查找

++头节点代表第0个位置++

cpp 复制代码
//按位置查找
LinkList GetElem(LinkList L, int SearchPos)
{
    int i = 0;
    if(SearchPos < 0)
    {
        return NULL;
    }
    while(L && i < SearchPos)
    {
        L = L->next;
        i++;
    }
    return L;
}
2.4.2 按值查找
cpp 复制代码
//按值 查找
LinkList LocateElem(LinkList L, ElemType SearchVal)
{
    while(L)
    {
        if(L->data ==SearchVal)
        {
            return L;
        }else
        {
            L =L->next;
        }
    }
    return NULL;

}

2.5 插入

插入情况

cpp 复制代码
bool ListFrontInsert(LinkList L, int InsertPose, ElemType InsertValue)
{
    LinkList  p = GetElem(L, InsertPose-1);

    if(p == NULL)
    {
        return false;
    }
    LinkList q ;
    q =(LinkList)malloc(sizeof(LNode));
    q->data = InsertValue;
    q->next = p->next;
    p->next = q;
    return true;

}

2.6 删除

删除注意的点:

  • 需要释放删除节点的空间
  • 需要判断删除的位置是否存在

​​​​​​​

cpp 复制代码
void dele_elem(ListLink L, int pos) {
    if (pos <0) {
        return ;
    }
    ListLink r,q; //q用来存储要删除的节点
    r = find_elem(L, pos -1);
    if (NULL == r) {
        return;
    }
    q=r->next;
    if (q==NULL)
    {return;}
    r->next = q->next;//断链
    free(q);
    q = NULL;//防止野指针
}

引用:要不要对变量进行赋值,如果不用不加引用,若要加引用

相关推荐
玉树临风ives20 分钟前
atcoder ABC 452 题解
数据结构·算法
无敌昊哥战神2 小时前
深入理解 C 语言:巧妙利用“0地址”手写 offsetof 宏与内存对齐机制
c语言·数据结构·算法
XH华3 小时前
数据结构第九章:树的学习(下)
数据结构·学习
会编程的土豆5 小时前
【数据结构与算法】再次全面了解LCS底层
开发语言·数据结构·c++·算法
songyuc6 小时前
BM2『链表内指定区间反转』学习笔记
学习·链表
摸个小yu6 小时前
【力扣LeetCode热题h100】链表、二叉树
算法·leetcode·链表
汀、人工智能6 小时前
[特殊字符] 第93课:太平洋大西洋水流问题
数据结构·算法·数据库架构·图论·bfs·太平洋大西洋水流问题
feng_you_ying_li7 小时前
C++11,{}的初始化情况与左右值及其引用
开发语言·数据结构·c++
锅挤8 小时前
数据结构复习(第一章):绪论
数据结构·算法