请编写程序,将 n 个整数顺次插入一个初始为空的单链表的表头。随后对任意给定的位序 i,删除链表中第 i 个结点。注意:i 代表位序,从 1 开始。删除结束后,输出链表长度,并顺序输出链表中的每个结点的数值。

输入格式:

输入首先在第一行给出正整数 n(≤104);随后一行给出 n 个 int 范围内的整数,数字间以空格分隔;最后一行给出删除位序 i,为 int 范围内的整数。

输出格式:

如果删除的位置不合法,则不能删除,在一行中输出句子 错误:删除位置不合法。。无论是否删除成功,都按照题面描述的要求,在一行中输出链表信息,格式为:

表长: x1 x2 ... xn

注意数字间有 1 个空格分隔,行首尾无多余空格。

输入样例 1:

5
1 2 3 4 5
3

输出样例 1:

4: 5 4 2 1

输入样例 2:

5
4 3 6 8 0
0

输出样例 2:

错误:删除位置不合法。
5: 0 8 6 3 4

代码如下:

#include<iostream>
typedef struct LNode
{
    int data;
    struct LNode *next;
}LNode,*LinkList;
using namespace std;
void CreateList(LinkList &L,int n)
{
    L=new LNode;
    L->next=NULL;
    for(int i=0;i<n;i++)
    {
        int num;
        cin>>num;
        LinkList p=new LNode;
        p->data=num;
        p->next=L->next;
        L->next=p;
    }
}
int DeleteLNode(LinkList &L,int i)
{
    if(i<1)
        return 0;
    int j=1;
    LinkList p=L;
    while(p&&j<i)
    {
        p=p->next;
        j++;
    }
    if(!p||!p->next)
        return 0;
        LinkList temp=p->next;
        p->next=temp->next;
        delete temp;
        return 1;
}
void PrintLNode(LinkList &L)
{
    LinkList p=L->next;
    int i=0;
    while(p)
    {
        cout<<" "<<p->data;
        p=p->next;
        i++;
    }
}
int main()
{
    LinkList L;
    int n;
    cin>>n;
    CreateList(L,n);
    int i;
    cin>>i;
    if(DeleteLNode(L,i))
    {
        cout<<n-1<<':';
    }else{
        cout<<"错误:删除位置不合法。"<<endl;
        cout<<n<<":";
    }
    PrintLNode(L);
    cout<<endl;
    return 0;
}

 做题小结:

1、在删除链表节点时,我们需要修改被删除节点的前驱节点的 next 指针。使用 p = L 可以让指针 p 遍历到要删除节点的前驱节点,从而顺利完成删除操作;而使用  p = L->next 会使指针直接指向第一个实际节点,在删除非第一个节点时,无法找到其前驱节点,导致无法完成删除操作。

2、p = L 的使用情况 :

1)遍历链表并访问每个节点(包括头节点):当需要对链表进行全面遍历,且要处理头节点以及后续所有节点的情况时,会使用 p = L。例如,打印链表所有节点的信息,包括头节点中可能存储的一些链表相关的元数据(如链表长度等),就需要从 L 开始遍历。

2)在链表头部插入节点:要在链表头部插入新节点,需要先将 p 指向头节点 L,然后通过修改 L 的 next 指针来插入新节点,使其成为链表的新第一个实际节点。

3)删除链表中的节点(需要找到前驱节点):在删除链表中任意位置的节点时,为了能够找到要删除节点的前驱节点,以便修改前驱节点的 next 指针来完成删除操作,需要从 p = L 开始遍历链表,直到找到前驱节点。

3、 p = L->next 的使用情况 :

1)遍历链表中的实际数据节点(不考虑头节点):如果确定不需要处理头节点,只关注链表中存储实际数据的节点,那么可以使用 p = L->next 来跳过头节点,直接从第一个实际数据节点开始遍历。例如,当链表的头节点仅用于存储链表的一些管理信息(如链表长度、链表类型标识等),而不存储实际数据时,遍历实际数据节点就可以从 L->next 开始。

2)查找特定数据节点(已知不在头节点中):当明确要查找的数据节点不会存储在头节点中,且链表有头节点时,可以从 p = L->next 开始查找,这样可以提高查找效率,减少不必要的比较操作。

更多推荐