C++语言入门--零基础学习笔记(6)

前言

本次我们要学习的是链表结构。类似于数组的顺序存储结构,很适合数据查找,但是如果我们要对数据的元素进行增加或者删除,采用顺序存储就要考虑到删减后移位的问题。而链表可以很有效的提高删减过程的效率。

1.指针

在学习链表之前,我们来学习指针。C++的指针就像是一个地址引用,它可以帮助我们访问和操作存储在地址中的数据。

//指针的声明,如果我们要声明一个指向整数的指针,我们有下面两种写法
int *ptr1;
int* ptr1; //两种方式是等效的
//如果想要存储某个变量的地址并获取地址所存储的值,我们需用到取地址符(&)以及解引用符(*)
int x = 10;
int *p = &x;//将x的地址赋给p
int value = *p;//获取p指针指向的值,即x,故value=10
//指针跟数组结合
int array[3]={0, 1, 2};
int *ptr = arr;//指向数组的第1个元素
int value = *(ptr + 2) //指向数组的第3个元素

除了上述之外,还有一个特殊的空指针,用于表示指针不执行任何有效的地址

int *ptr = nullptr;//初始化空指针

2. 链表

进入主题,链表可以像数组一样是顺序存储的,也可以是不连续的。链表的每一个节点含有一个数据域,用来存放数据;以及一个指针域,用来指向下一个结点的位置。
Fig. 1 链表结构
其中,最后一个结点的指针所指向的位置是不存在的,也就是空。链表的第一个节点的存储位置被称为头指针,然后通过next指针域找到下一个节点。为了简化链表的插入和删除操作,我们经常在链表的第一个节点前添加一个节点,称为虚拟头节点(dummyNode)头节点的数据域可以是空的,但是指针域指向第一个节点的指针。

3. 案例

下面从一个案例来熟悉链表的操作。例子来源于代码随想录基础课程。
输入描述:
每次输出只有一组测试数据。
1. 每组的第一行包含一个整数 k,表示需要构建的链表的长度。
2. 第二行包含 k 个整数,表示链表中的元素。
3. 第三行包含一个整数 S,表示后续会有 S 行输入,每行两个整数,第一个整数为 n,第二个整数为 x ,代表在链表的第 n 个位置插入 x。 S 行输入…
4.在 S 行输入后,后续会输入一个整数 L,表示后续会有 L 行输入,每行一个整数 m,代表删除链表中的第 m 个元素。L 行输入…
输出描述:
包含多组输出。
1. 每组第一行输出构建的链表,链表元素中用空格隔开,最后一个元素后没有空格。
2. 然后是 S 行输出,每次插入一个元素之后都将链表输出一次,元素之间用空格隔开,最后一个元素后没有空格
3. 如果插入位置不合法,则输出“Insertion position is invalid.”。
代表在链表的第 n 个位置插入 x。 S 行输入…
4.然后是 L 行输出,每次删除一个元素之后都将链表输出一次,元素之间用空格隔开,最后一个元素后没有空格;
5.如果删除位置不合法,则输出“Deletion position is invalid.”。
输入示例:

5
1 2 3 4 5
3
4 3
3 4
9 8
2
1
0

输出示例:

1 2 3 3 4 5
1 2 4 3 3 4 5
Insertion position is invalid.
2 4 3 3 4 5
Deletion position is invalid.

代码:

#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,s,n,x,L;
    cin >> k;
    int Listlenth = k; //链表长度
    ListNode *dummyHead = new ListNode(0); //创建头节点
    ListNode *cur = dummyHead;
    // 读取数据
    for (int i=0; i<k; i++)
    {
        cin >> val;
        ListNode *newNode = new ListNode(val);
        cur->next = newNode;
        cur = cur->next;
    }

    //添加节点
    cin >> s;
    while (s--)
    {
        cin >> n >>x;
        if (n <= 0 || n>Listlenth)
        {
            cout << "Insertion position is invalid." <<endl;
            continue;
        }
        //重设置为头指针
        cur = dummyHead;
        //寻找添加节点的位置,讲cur移到n-1位置
        for (int i = 1; i<n; i++) cur= cur->next;
        
        //插入链表
        ListNode *newNode = new ListNode(x);
        ListNode *temp = cur->next;
        cur->next = newNode;
        newNode->next = temp;
        Listlenth++;  //链表长度+1
        
        //打印链表
        printLinklist(dummyHead);
        
    }
    //删除节点
    cin >> L;
    int a;
    while(L--)
    {
        cin >> a;
        if ( a<= 0 || a>Listlenth)
        {
            cout << "Deletion position is invalid." <<endl;
            continue;
        }
        //重设置为头指针
        cur = dummyHead;
        for (int i=1; i<a; i++) cur=cur->next;
        cur -> next=cur->next->next;
        Listlenth--;
        
        //打印链表
        if(Listlenth !=0) printLinklist(dummyHead);
    }

    
    return 0;
}

4. 总结

以上即是本次的学习内容。

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值