数据结构 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;//防止野指针
}

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

相关推荐
小辉同志2 小时前
215. 数组中的第K个最大元素
数据结构·算法·leetcode··快速选择
风一样的航哥5 小时前
LeetCode 2615 等值距离和:前缀和优化O(n)解法深度解析
数据结构·算法·leetcode
khalil10207 小时前
代码随想录算法训练营Day-34动态规划03 | 01背包问题 二维、01背包问题 一维、416. 分割等和子集
数据结构·c++·算法·leetcode·动态规划·背包问题·01背包
空中海8 小时前
Redis 从零到精通:9大数据结构 × 11个高频工程实战场景完全手册
数据结构·数据库·redis
地球资源数据云9 小时前
1951-2025年中国逐年1千米逐月总降水量区域统计数据集_年表_县
大数据·数据结构·数据库·数据仓库·人工智能
cpp_250110 小时前
P2639 [USACO09OCT] Bessie‘s Weight Problem G
数据结构·算法·动态规划·题解·洛谷·背包dp
郝学胜-神的一滴10 小时前
[力扣 227] 双栈妙解表达式计算:从思维逻辑到C++实战,吃透反向波兰式底层原理
java·前端·数据结构·c++·算法
菜鸟丁小真11 小时前
LeetCode hot100 -131.分割回文串
数据结构·算法·leetcode·知识点总结
数智化精益手记局11 小时前
8d报告案例分析:拆解8d报告案例分析的8个步骤,解决生产现场重复发生的质量难题
大数据·数据结构·数据库·人工智能·精益工程
笨笨饿11 小时前
66_C语言与微控制器底层开发
linux·c语言·网络·数据结构·算法·机器人·个人开发