链表有无头结点的区别:删除链表的倒数第N个结点

一、链表的结构

定义:是一组任意的储存单元来存放线性表的结点,这种存储单元可以是连续的,也可以是非连续的
特点:链表中结点的逻辑次序和物理次序不一定是相同
结点组成:数据域与指针域
单链表结点结构如下图:
**加粗样式**
N个结点链接成一个链表,即为线性表的链式存储结构,又因为只有一个指针域,又被称为单链表,或线性链表。
整个链表的存取必须从头开始,链表中第一个结点的位置叫做头指针,由于最后一个元素没有直接后继,则线性表的最后一个结点的指针为“空”(NULL),如下图:
在这里插入图片描述
有时为了方便对链表的操作,会在链表的第一个结点前加上一个结点,称为头结点,头结点一般不存储任何信息,有时存储线性表长度等附加信息。如下图:
在这里插入图片描述
头指针与头结点的比较:
在这里插入图片描述

二、案例分析:LeetCode-19

题意给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点
解题思路
删掉倒数第N个数,实际就是删掉第Length - N+1个数(删掉第一个元素:length - length + 1)
1.获取链表的长度Length
2.使结点指针p指向待删除的前一个位置
3.p->next = p->next->next //待删除结点的后驱给前驱
注意两种:当结点为0 的时候,与删除结点是最后一个结点的时候

代码1:使用头指针

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
    struct ListNode* p=head;  //定义一个结点指针p,与head指向第一个结点
    int i=0,length=0;
    while(p != NULL) //遍历结点获取链表的长度
    {
        p=p->next;
        length++;
    }
    for(i=1,p=head;i<length-n;i++) //使指针走到待删除结点的前一个结点
    {
        p=p->next;
    }
    if(length==0) //链表为空的时候
        head=NULL;
    else if(length-n==0) //删除第一个位置结点,头指针会变化
        head=head->next;
    else
        p->next=p->next->next; //删除其他位置结点
    return head;
    
}
输入:[1 2 3 4 5]
预期输出:[1 2 3 5]

在这里插入图片描述
代码二:带头结点

int getLength(struct ListNode* head) {
    int length = 0;
    while (head) {
        ++length;
        head = head->next;
    }
    return length;
}

struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
    struct ListNode* h = malloc(sizeof(struct ListNode));
    h->val = 0, h->next = head;
    int length = getLength(head); 
    struct ListNode* p = h;
    for (int i = 1; i < length - n + 1; ++i) {
        p = p->next;
    }
    p->next = p->next->next;
    struct ListNode* ans = h->next;
    free(h);
    return ans;
}

在这里插入图片描述
可以很清楚的发现头指针与头结点的应用上的区别:
1、若不使用头结点,必然要对第一个结点的删除或者其他操作进行判断。
2、而使用头结点,首先得开辟一个结点空间,使用完后释放头结点
好处;不必考虑第一个结点处理问题,只需要返回头结点的后一个结点位置信息即可
即上述代码中结点指针ans,代码更加清晰明白!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值