数据结构—链表详解

浅谈数据结构——链表

本篇随笔就数据结构——链表进行讲解。链表是一种特别实用的数据结构,我把它理解为数组的升级版,也就是在数组的基础上,它能做到在任意位置添加或者删除元素,而不影响其他元素。链表还是我们进行图论学习时,图的常用存储方式——邻接表(链式前向星)的实现基础。学习链表需要读者具有一定的语法基础,最好会一点点指针。(不会也没关系,我们主要讲解数组模拟链表)

什么是链表

链表,顾名思义,就是带链的表。我已经说过,链表属于数组的加强版。那我们可以借助数组来理解链表:如果说数组是一长排连在一起的“方块”的话,那么链表就是把这些方块“拉开“,每个方块还有两个箭头,分别指向这个方块前面的方块和后面的方块。

这样我们就可以理解,为什么链表可以支持随机插入和删除了。从某种意义上来说,这里的每一个方块都是离散的,我们在某两点插入的时候,只需要把要插入的元素,这个元素目标位置前面的元素、后面的元素的箭头改一下,就做到了插入的操作。删除同理。

链表的实现原理

根据刚才的理解,我们可以发现,我们可以用一个结构体来模拟每一个方块,结构体中存一个元素和两个指针,指针分别指向上一个元素的位置和下一个元素的位置。但是蒟蒻不会指针指针的实现比较麻烦,而且在调试的时候也不是很理想。所以我们来想指针的本质就是告诉你一个位置,那么针对于”加强数组“链表来讲,这个位置可以用什么来表示呢?

对,数组下标。

所以我们刚才的结构体就可以简化,变成存一个元素和两个int变量(存储数组下标)。这样,我们就可以用结构体数组模拟链表的实现。

链表基本操作的代码实现

链表实现的精髓就是更改指针,改掉了三个元素(前,中,后)的指针使链表合法,就完成了我们需要做的操作,本部分不再就每段代码进行过多讲解,请大家自行理解代码含义,最好借助纸笔推演,看的会更明白一些。

(1)初始化

我们初始化链表的时候,要根据题目意思处理开头的第一个元素,这很重要!并且,我们把所有的指针都清成-1,这样保证了链表初始绝对合法。

void init()
{
    for(int i=1;i<=n;i++)
        a[i].pre=a[i].nxt=-1;
    a[1].nxt=-1;
    a[1].pre=0;
    a[0].nxt=1;
}

(2)插入操作

void insert_left(int pos,int k)//把元素k插入到pos元素之前
{
    a[a[pos].pre].nxt=k;
    a[k].pre=a[pos].pre;
    a[pos].pre=k;
    a[k].nxt=pos;
}
void insert_right(int pos,int k)//把元素k插入到pos元素之后
{
    a[a[pos].nxt].pre=k;
    a[k].nxt=a[pos].nxt;
    a[pos].nxt=k;
    a[k].pre=pos;
}

(3)删除操作

void remove(int x)
{
    if(a[x].pre==-1)
        return;
    a[a[x].pre].nxt=a[x].nxt;
    a[a[x].nxt].pre=a[x].pre;
    a[x].pre=-1;
    a[x].nxt=-1;
}

(4)遍历

void print()
{
    int start=a[0].nxt;
    while(1)
    {
        printf("%d ",start);
        if(a[start].nxt==-1)
            break;
        start=a[start].nxt;
    }
}

转载于:https://www.cnblogs.com/fusiwei/p/11387165.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
链表是一种常见的数据结构,用于存储一系列的元素。在Java链表可以使用LinkedList类来实现。下面是关于Java链表的详细解释: 链表由节点(Node)组成,每个节点包含两部分:数据域(存储元素的值)和指针域(指向下一个节点的指针)。链表的头节点是链表的起始点,尾节点是链表的结束点。 Java的LinkedList类实现了List接口和Deque接口,因此可以用作列表和双端队列。LinkedList在内存以链式结构存储元素,相邻元素通过节点的指针连接。 与数组相比,链表的一个优势是可以快速地插入和删除元素。由于链表的元素在内存不连续存储,所以插入和删除只需要改变指针的指向,而不需要移动其他元素。然而,链表的一个劣势是访问特定索引的元素比较慢,因为需要从头节点开始遍历链表。 下面是一些常用的操作示例: 1. 创建一个空链表: LinkedList<String> list = new LinkedList<>(); 2. 在链表末尾添加元素: list.add("A"); list.add("B"); list.add("C"); 3. 在指定位置插入元素: list.add(1, "D"); // 在索引为1的位置插入元素D 4. 获取链表的大小: int size = list.size(); 5. 获取指定索引位置的元素: String element = list.get(2); // 获取索引为2的元素 6. 修改指定索引位置的元素: list.set(0, "E"); // 将索引为0的元素修改为E 7. 删除指定索引位置的元素: list.remove(1); // 删除索引为1的元素 8. 遍历链表: for (String element : list) { System.out.println(element); } 需要注意的是,LinkedList类不是线程安全的,如果在多线程环境使用链表,需要进行适当的同步处理。此外,由于链表的元素不是连续存储,所以对于大量元素的访问和操作,可能会导致性能下降。在这种情况下,可以考虑使用ArrayList或其他更适合的数据结构
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值