卡码网C++基础课笔记 | 15.链表的基础操作III

题目:

 

代码:

 1、使用构造函数的方法

#include<iostream>
using namespace std;
struct ListNode
{
    int val;
    ListNode *next;
    ListNode(int x):val(x),next(NULL){}
};
//创建链表
void getList(int n,ListNode *dummyHead)
{
    ListNode *cur=dummyHead;
    while(n--)
    {
        int val;
        cin>>val;
        ListNode *newNode=new ListNode(val);
        cur->next=newNode;
        cur=cur->next;
    }
}

//输出链表元素
void printList(ListNode *dummyHead)
{
    ListNode *cur=dummyHead;
    while(cur->next!=NULL)
    {
        cur=cur->next;
        cout<<cur->val<<" ";
    }
    cout<<endl;
}

//在链表的第n个位置插入x
void ListInsert(int n,int x,ListNode *dummyHead)
{
    ListNode *cur=dummyHead;
    for(int i=0;i<n-1;i++)
    {
        if(cur->next!=NULL) cur=cur->next;
        else break;
    }
    //链表节点的插入过程
    ListNode *temp=cur->next;//定义temp用来存储插入前的next指针指向的节点
    ListNode *newNode=new ListNode(x);
    cur->next=newNode;
    newNode->next=temp;
}

//删除链表中的第m个元素
void ListDelete(int m,ListNode *dummyHead)
{
    ListNode *cur=dummyHead;
    for(int i=0;i<m-1;i++)
    {
        if(cur->next!=NULL) cur=cur->next;
        else break;
    }
    cur->next=(cur->next)->next;//next指针指向下一个节点实现删除节点
}


int main()
{
    ListNode *dummyHead=new ListNode(0);
    int k,S;
    cin>>k;//k表示链表长度
    getList(k,dummyHead);
    cin>>S;
    while(S--)
    {
        int n,x;
        cin>>n>>x;
        if(n>0&&n<k+2)//插入位置可以是1到k+1
        {
            ListInsert(n,x,dummyHead);
            k++;
            printList(dummyHead);
        }
        else cout<< "Insertion position is invalid."<<endl;
    }
    int L;
    cin>>L;
    while(L--)
    {
        int m;
        cin>>m;
        if(m>0&&m<k+1)//删除位置可以是1到k
        {
             ListDelete(m,dummyHead);
             k--;
             if(k>0) printList(dummyHead);
        }
        else cout<<"Deletion position is invalid."<<endl;
    }
    return 0;
}

2、不使用构造函数的方法

#include <iostream>
using namespace std;
struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(nullptr) {}
};
// 打印链表
void printLinklist(ListNode* dummyHead) {
    ListNode* cur = dummyHead;
    while (cur->next != NULL) {
        cout << cur->next->val << " ";
        cur = cur -> next;
    }
    cout << endl;
}
int main() {
    int k, val;
    ListNode* dummyHead = new ListNode(0); // 创建了一个虚拟头结点
    cin >> k;
    int listLen = k; //记录链表长度,用来控制非法输入输出
    ListNode* cur = dummyHead; // 定义一个指向当前节点的指针 cur,初始指向虚拟头结点
    for (int i = 0; i < k; i++) { // 或者使用while(n--)
        cin >> val;
        ListNode* newNode = new ListNode(val); // 构造一个新的节点
        cur -> next = newNode; // 将新节点接入链表
        cur = cur -> next;      // cur 指向下一个节点
    }
    // 增加节点
    int s, n, x;
    cin >> s;
    while (s--) {
        cin >> n >> x;
        if (n <= 0 || n > listLen) { // 当要插入的位置非法时
            cout << "Insertion position is invalid." << endl;
            continue;
        }
        // 指针重新指向虚拟头结点,准备用cur遍历链表
        cur = dummyHead;

        // 寻找添加节点的位置,i从1开始,因为节点计数从1开始
        // 如果这个for循环看不懂,可以模拟一下n为1,链表长度为1的场景
        for (int i = 1; i < n; i++) cur = cur->next;

        // 插入节点
        ListNode* newNode = new ListNode(x); // 构造一个新的节点
        ListNode* tmp = cur ->next;
        cur->next = newNode;
        newNode->next = tmp;

        // 链表长度加1
        listLen++;

        // 打印链表
        printLinklist(dummyHead);

    }

    // 删除节点
    int l,m;
    cin >> l;
    while (l--) {
        cin >> m;
        if (m <= 0 || m > listLen) {
            cout << "Deletion position is invalid." << endl;
            continue;
        }
        // 指针重新指向虚拟头结点,准备用cur遍历链表
        cur = dummyHead;

        //开始寻找删除节点的位置,i从1开始,因为节点计数从1开始
        for (int i = 1; i < m; i++) cur = cur->next;

        // 删除节点
        cur->next = cur->next->next;

        listLen--; // 链表长度减一

        // 如果删除节点后链表为空则不打印
        if (listLen != 0) printLinklist(dummyHead);
    }
}

1、插入链表的过程

image-20230912120144709

        我们可以假设这样一个场景:在传递情报过程中,A的下线是B, 也就是A -> next = B, 现在我们要引入一个C充当A和B之间的中间人,A的下线是C, C的下线是B,我们可以直接将A的next指向C,即A -> next = C, 然后将C的next指向B, 但是B无法直接表示,之前是用A -> next来表示B的,现在A -> next已经指向C了,所以在操作之前,我们需要实现定义一个变量保存B,假设为temp, 然后将C的next指针指向B即可。

在链表中,具体插入的过程如下:

  • 找到要插入的位置的前一个节点,将之命名为cur, 要插入的位置的下一个节点,将之命名为temp它们之间的关系是temp=cur -> next 
  • 创建一个新的链表newNode, 将curnext指针指向newNode, 即cur -> next = nowNode
  • newNodenext指针指向temp, 即newNode -> next = temp

这样就完成了链表节点的插入过程。转换成代码如下:

// 创建了一个新的 ListNode 结构的节点,值为x, 并将其地址赋给指针 newNode
ListNode *newNode = new ListNode(x);
// 创建了一个名为 temp 的指针,临时存储当前节点 cur 的下一个节点的地址。
ListNode *temp = cur ->next;
// 将当前节点 cur 的 next 指针更新为指向新节点 newNode,将新节点插入到当前节点后面。
cur->next = newNode;
// 将新节点 newNode 的 next 指针设置为指向之前临时存储的节点 temp
newNode->next = temp;

2、删除链表的过程

image-20230912115756421

删除链表的过程则比较简单,只需要找到删除节点的前一个节点cur, 并将其next 指针设置为指向当前节点的下下个节点,从而跳过了下一个节点,实现了节点的删除操作。转换成代码如下:

// cur->next 表示当前节点 cur 的下一个节点
// cur->next->next 表示要删除的节点的下一个节点
// 当前节点 cur 的 next 指针不再指向要删除的节点,而是指向了要删除节点的下一个节点
cur->next = cur->next->next;

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值