单链表 插入 删除

ALcohol_可豪 大一暑假算法与数据结构学习笔记

1 插入:链表增加元素,首部、中间和尾部分别会有什么问题,该如何处理?

先给出示例代码:

ListNode* ListNode::insertNode(ListNode* head, ListNode* nodeInsert,int position)
{
    if(head == NULL)//如果是空链表,那么待插入的节点就是链表的头节点
        return nodeInsert;
    int size = getListLength(head);
    if(position > size + 1 || position < 1)
    {
        cout<<"out of bound"<<endl;
        return head;
    }
    //头插
    if(position == 1)
    {
        nodeInsert->next = head;
        head = nodeInsert;
        return head;
    }

    ListNode* pre = head;
    int count = 1;
    while(count < position - 1)
    {
        pre = pre->next;
        count++;
    }
    nodeInsert->next = pre->next;
    pre->next = nodeInsert;
    return head;
}

首先分析参数:head是指向头节点的指针,nodeInsert是待插入的指针,position是插入位置的后一个节点序号

对链表的数量进行分类,有空链表和非空链表
对于【空链表】,插入的节点就是链表的头节点,返回值也是头节点的指针。

if(head == NULL)
	return nodeInsert;

考虑越界的情况

int size = getListLength(head);
if(position > size + 1|| position < 1) //@0
{cout<<"out of bound"<<endl; return head;}

@0:为什么position>size + 1是判定条件?
因为position的意义是待插入位置的后一个节点。
如果position=size+1,说明为尾插,即插入在链表屁股上。


对于【非空链表】,插入的节点又分为两种,一种是头插,即插入在所有链表之前,另一种是中间插入(包括中间和尾插)

对于头插,需要注意的是头插的判定,当position为1的时候判定为头插:

int size = getListLength(head);
if(position == 1)
	nodeInsert->next = head;
	head = nodeInsert;
	return head;

对于中部插入和尾部插入,实际上是一样的。尾部插入可以看成是中部插入的一个特例。
首先需要找到链表插入位置的前一个节点。然后进行节点的连接。

ListNode* pre = head;
int count = 1;
while( count < position - 1 ) //@1
{
	count++;
	pre = pre->next;
}

@1:为什么下面是判定条件是( count < position - 1)呢?
例如当postion为1时,插入位置为链表头,上面已经处理过了,这里不会出现position为1的情况;
而position为2时,count<position -1;直接判定为假,跳出循环,这个时候pre指向的就是head,而我们需要插入的位置,就是第position位置的前一个空挡,pre找到了position位置的前一个节点。

下面进行插入

   nodeInsert->next = pre->next;
   pre->next = nodeInsert;
   return head;

为什么尾插被包括在上面了?
因为尾插入时,pre指向最后一个节点,pre->next == NULL
nodeInsert->next = NULL; 逻辑正确

完成插入。

2 链表删除元素,首部、中间和尾部分别会有什么问题,该如何处理?

先给出示例代码

ListNode* ListNode::deleteNode(ListNode* head, int position)
{
    if(head == NULL)
        return NULL;
    int size = getListLength(head);
    if(size<1 || size>position)
    {
        cout<<"error of outBound"<<endl;
        return head;
    }
    if(position == 1)
    {
        return head->next;
    }
    else
    {
        ListNode* pre = head;
        int count = 1;
        while(count<position-1)
        {
            pre = pre->next;
            count++;
        }
        ListNode* cur = pre->next;
        pre->next = cur->next;
    }
}

先理解参数含义,head是头节点指针,position是待删除节点序号。返回值为删除后的头节点指针。

首先判断链表为空的情况

if(head == NULL)
	return head;

如果链表不为空,判断待删除节点是否存在。

int size = getListLength(head);
if(position < 1 || position > size)
{cout<<"out of bound"<<endl;	return head;}

如果position位置存在,下面开始删除
首先如果是头删,直接让头节点指向下一个节点即可
不用担心下一个节点是不是空,因为即便只有一个节点,删除后为空那么返回一个空链表也是符合逻辑的。

if(position == 1)
	return head->next;

如果下一个链表是中间位置或者末尾

if(position == 1)
	return head->next;
else
{
	ListNode* pre = head;
	int count = 1;
	while(count < position -1 )
	{
			coun++;
			pre = pre->next;
	}
	ListNode* cur = pre -> next;
	pre->next = cur ->next;
}
return head;

这个和上面插入是相同的,找到待操作位置的前一个节点,然后执行操作。对于中间操作和尾部操作代码可以通用。
完成删除。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值