链表基础

什么是链表

数组是连续的,每当我们需要在数组当中插入或删除数组中间的数据时,都必须要移动大量的元素,效率低下

数组是保存在内存当中的一组连续的格子

程序事先会保存数组的地址,当我们需要访问数组当中的某个数组时,只需要让数组地址加上偏移值即可

例如:a数组地址为1000,那么a[4]的地址就是:1004

与数组不同的是,组成链表的格子不是连续的,它们可以分步在各个地方,这种不相邻的格子,就叫做结点

既然分步在各个地方,那么计算机是通过什么东西来寻找链表当中的节点呢?

采用指针的方式来完成这步操作

每个结点除了保存数据,它还保存着链表里下一个结点的内存地址

这份用来指示下一个结点的内存地址的额外数据,被称为

结点

结点

在图示当中,每个结点的后一个格子都指向后一个结点的前一个格子

因此,如果我们想要知道链表在内存当中的位置,就必须要明确第一个格子的位置

  • 将数据分散到内存各处,不需要连续
  • 插入删除的效率较高
  • 将数据存放在一系列连续的空间中
  • 插入和删除需要移动元素,效率较低

实现一个链表

对于结点来说,既要能够保证存储数据,又要能够存储下一个结点的内存地址,应该采用那种数据结构最为合适呢?

一个节点当中需要包含两种不同的数据类型,采用结构体的方式最为合适

  • 数据类型:int   float   string  char
  • 地址类型:指针

答案

节点的实现方式

struct test
{
    int data;   //保存数据的部分
    test *next; //保存下一个结点的指针部分
};
  • 数据部分可以是任何已知的数据类型
  • 指针部分是一个test类型,因为它保存的是下一个test结点

创建多个节点

test a;
a.data = 'a';

test b;
b.data = 'b';

test c;
c.data = 'c';

test d;
d.data = 'd';
  • 创建一个test类型的结点
  • 给结点的data部分赋值

将节点之间进行链接

a.next = &b;
b.next = &c;
c.next = &d;
d.next = nullptr;   //d的next并不会指向任何一个结点,所以是空节点
  • 创建一个test类型的结点
  • 给结点的data部分赋值
  • nullptr表示这个节点为空,不指向任何一个结点

读取链表

如果我们要找到链表当中的某个值,我们是没有办法像数组一样进行快速定位,比如:a[4]

因为我们不能很快的确定结点在内存当中的位置

因此,对于链表来说,我们只能先找到第一个结点的数据,再以此找到第二个结点、第三个结点

输出第一个结点的数据

cout << a.data << endl;

输出第二个结点的数据

cout << a.next->data << endl;

输出第三个结点的数据

cout << a.next -> next -> data << endl;

利用循环的方式来读取链表的值

test temp = a;  //建立临时变量,用于指向结点
while (temp.next != nullptr){
  cout << temp.data << endl;
  temp = *temp.next;  //修正临时变量
}   
cout << temp.data << endl;  //打印最后一个结点的内容
a
b
c
d

综合练习

从尾到头打印链表

请新建一个链表,并将链表结点的数据,从尾到头进行打印

链表数据:78  45  12  56  63  14  78

从尾到头打印结果:78  14  63  56  12  45  78
#include <iostream>

using namespace std;

struct number
{
    int data;
    number *next;
};

int main(){

    int acache[7] = {0};

    //建立链表

    number a,b,c,d,e,f,g;
    a.data = 78;a.next = &b;
    b.data = 45;b.next = &c;
    c.data = 12;c.next = &d;
    d.data = 56;d.next = &e;
    e.data = 63;e.next = &f;
    f.data = 14;f.next = &g;
    g.data = 78;g.next = nullptr;

    //遍历链表,将遍历的结果放在数组acache当中
    number temp = a;
    int i = 0;
    while (temp.next != nullptr){
        acache[i] = temp.data;i++;
        temp = *temp.next;
    }
    acache[i] = temp.data;

    //倒序输出结果
    for (int k = i;k >= 0;k--){
        cout << acache[k] << endl;
    }
}
Made with Slides.com