数据结构(C语言版)第二章线性表之链式存储结构(单链表)

本文深入探讨了线性链表的链式存储结构,详细介绍了单链表的读取、插入、删除及整表创建与删除等核心操作,并提供了具体的C语言实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、线性表链式存储结构
1、特点:用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的。也就是说这些数据元素可以存在内存没有被占用的任意位置。

2、节点由数据域和指针域组成。其中数据域存放数据元素,指针域存放后继节点的地址。

3、头指针与头节点的区别:
(1)头指针是链表指向第一个节点的指针,如果链表有头节点,则是指向头节点的指针;并且无论链表是否为空,头指针都不为空。
(2)头节点是放在第一元素节点之前的节点,数据域一般无意义,头节点不一定是链表的必要元素。

4、注意:
(1)在整个链表中,只有头节点有名字,其他数据节点没有名字,需要通过指针来访问;
(2)空链表没有数据节点,但是有头节点;
(3)销毁链表时不需要销毁头节点;

二、线性链表的抽象数据结构

#include<stdio.h>
#include<stdlib.h>
#include maxsize 1000
typedef struct node
{
   int data[maxsize];
   struct Node *next;
 }Node;
 typedef struct Node *Linklist;

1、单链表
1.1单链表的读取

int GetElem(Linklist L,int i,int *e)
{
    //L是带有头节点的单链表的头指针
    //当第i个元素存在时,赋值给e并返回1,否则返回0
    Linklist p;//声明指针
    int j=1;//用于计数
    p=L->next;//初始化,p指向链表的第一个节点
    while(p && j<=i)
    {
        p=p->next;
        ++j;
    }
    if(!p || j>i )
        return 0;
    *e=p->data;//取第i个节点的数据值
    return 1;
}

1.2单链表的插入
在链表L的第i个位置之前插入数据e,L长度增加1

int InsertElem (Linklist *L,int i,int e)
{
    Linklist p,s;//声明指针(变动指针和插入数据的指针)
    p = *L;//p指向链表的头指针
    int j=1;//计数
    while(p && j<i)
    {
        //寻找第(i-1)个节点位置,就是要插入数据的位置
        p = p->next;
        ++j;
    }
    if(!p || j>i)
        return 0;
    s=(Linklist)malloc(sizeof(Node));//生成新节点
    s->data=e;//找到位置,数据赋值
    s->next=p->next;//重点!
    p->next=s;//顺序不能错!
    return 1;
}

1.3单链表的删除
将链表L第i个节点删除,用e返回其值,L长度减1

int DelElem(Linklist *L,int i,int *e)
{
    Linklist p,q;//声明指针(变动指针和要删除的指针)
    int j=1;//计数
    p=*L;//指向链表的头指针
    while(p && j<i)//寻找第i-1个节点
    {
        p=p->next;
        ++j;
    }
    if(!p || j>i)
        return 0;
    q=p->next;
    p->next=q->next;
    *e=q->data;
    free(q);
    return 1;
}

1.4单链表的整表创建
方法一:头插法(后插入的在前面)

int CreateAll1(Linklist *L,int n)
{
    Linklist p;
    int i;
    *L=(Linklist)malloc(sizeof(Node));
    (*L)->next=NULL;//建立带头节点的单链表
    for(i=0;i<n;i++)
    {
        p=(Linklist)malloc(sizeof(Node));//生成新节点
        scanf("%d",&p->data);//输入数据
        p->next=(*L)->next;//重点!
        (*L)->next=p;//顺序不能错,和单链表的插入类似
    }
}

方法二:尾插法(后插的在后面)

int CreateAll2(Linklist *L,int n)
{
    Linklist p,r;
    int i;
    *L=(Linklist)malloc(sizeof(Node));
    r=*L;//r是指向尾部的节点
    for(i=0;i<n;i++)
    {
        p=(Linklist)malloc(sizeof(Node));
        scanf("%d",&p->data);
        r->next=p;//将尾节点的指针域设置为新节点
        r=p;//更新尾部节点
    }
    r->next=NULL;//表示当前链表结束
}

1.5单链表的整表删除

/*单链表的整表删除*/
int DelAll(Linklist *L)
{
    Linklist p,q;
    p=(*L)->next;//指向第一个节点
    while(p)
    {
        q=p->next;//将下一个节点赋值给q
        free(p);//释放当前节点
        p=q;//达到循环释放
    }
    (*L)->next=NULL;//头节点的指针域为空
    return 1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值