数据结构之单链表相关

本文介绍了单链表的相关知识,包括头指针、头结点和首元结点的概念。单链表分为不带头节点和带头节点两种,前者不利于特定操作,后者更方便。还阐述了单链表的插入方法,如头插法和尾插法,并给出了带头结点和不带头结点的初始化及插入的整体代码思路。

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

头指针:

是指链表指向第一个结点的指针(若有头节点,则指向头结点,否则指向首元结点)。
头指针具有标识作用,用头指针冠以链表的名字;每次访问链表时都可以从头指针依次遍历链表中的每个元素
头指针意义在于,在访问链表时,总要知道链表存储在什么位置(从何处开始访问),即头指针相当于记录了链表的起始物理地址。然后由于链表的特性(next指针),知道了第一个结点地址,那么整个链表的元素都能够被访问,所以头指针是必须存在的。

头结点:

可有可无。为了操作的统一与方便而设立的,放在第一个元素结点之前,其数据域一般无意义(当然有些情况下也可存放链表的长度)

首元结点:

即链表的第一个元素结点,它是头结点后边的第一个结点。

单链表分为两种:

(1)不带头节点的链表:此种链表的head即保存第一个数据,访问时从head开始。不利于删除或者添加指定位置数据的操作。
(2)带头节点的链表:此种链表保存数据是从head->next开始的,head中并未保存有数据,访问时自然head->next开始,优点就是方便操作。

单链表的插入:

向链表中插入一个新的节点时,首先由新建一个节点p,将其指针域赋值为空指针(p->next = NULL),然后在链表中寻找适当的位置执行节点的插入操作。

1、若链表为空:
无头结点时:则将新节点p作为首元节点,让head指向新节点p

head = p

有头结点时:

*r = *head
r->next = p
r = p

其中,r作为移动指针,每次都移动至链表最后一个节结点,方便后续尾插入

2、若链表不为空:
a、头插法(有头节结点,head指向头结点)(类似与中间插入)

p->next = Head->next;
Head->next = p;

如何理解该段代码:
Head 是头指针,其实代表头结点的物理地址
Head->next 代表头结点的指针域,里面存储的是头结点下一个结点(首元节点)的物理地址(可以说成Head->next代表首元结点的地址)
p->next 是p结点的指针域,里面需要储存的是p结点的下一个结点的物理地址
p->next = Head->next 把Head->next赋值给p->next,即先在p->next也指向了首元结点
Head->next = p 再把头结点指向新节点p,此时p结点变为首元结点

链表代码中的 = 可以理解为“指向”,即“左边”“指向”“右边”

在这里插入图片描述

b、头插法(无头结点,head指向首元结点)

p->next = Head;
Head = p;

c、尾插法

for(t = Head; t->next; t=t->next); //结束时t指向尾节点
p->next = NULL; //进行插入
t->next = p;
t = p;//t指向尾结点

在这里插入图片描述

整体代码

带头结点初始化:带头结点尾插入,统一操作。


Node *head;  //声明头结点
void InitList(Node **head){
    *head=(Node *)malloc( sizeof(Node));
    (*head)->next=NULL;
}

方式1:调用CreatList(&head);

void CreatList(Node **head){
     Node *r=*head,*s;
     int a;
     while(scanf("%d",&a)){
          if(a!=0){
               s=(Node *)malloc(sizeof(Node));
               s->value=a;
               r->next=s;
               r=s;   
          }
          else{   
               r->next=NULL;
               break;   
          }
     }
}

方式2 :调用CreatList(head);

void CreatList(Node *head){
     Node *r=head,*s;
     ... //下面的都一样
}

不带头结点初始化:

方式1:调用InitList(&head);

void InitList(Node **head){
*head=NULL;
}

方式2:调用InitList(head);

void InitList(Node *head){
    head=NULL;
}

不带头结点尾插入,第一个节点与其他节点分开操作。

void CreatList(Node  **head){
     Node *p,*t;         /*p工作指针,t临时指针*/
     int a,i=1;
     while(scanf("%d",&a)){
          if(a!=0){
               t=(Node *)malloc(sizeof(Node));
               t->value=a;
               if(i==1){
                    *head=t;   
               }
               else{
                    p->next=t;
               }
               p=t;
          }
          else{   
               p->next=NULL;
               break;   
          }
          i++;
     }
}

整体代码链接点击此处

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值