链表及数组模拟链表

转载请注明出处,部分内容引自百度百科、谭浩强《C程序设计》、蜗牛君的奋斗史大神的博客



前置知识:    C语言入门



数组党的福音(本蒟蒻学链表时不会指针,然而好像所有人都拿指针写)
首先,我们需要知道什么是链表
百度百科
看不懂勿喷(毕竟百度百科也不是用来让人看懂的)
我们可以从中得出链表的特性:
链表是一种物理存储单元上非连续、非顺序的存储结构
提取主谓宾:链表是存储结构。我认为这就是链表的本质——一种数据结构。
那么非连续、非线性有什么含义呢?这表明链表的内存是不连续的,前一个元素存储地址的下一个地址中存储的不一定是下一个元素。链表通过一个指向下一个元素地址的引用将链表中的元素串起来。
链表分为三类:单向链表、双向链表、循环链表
1,单向链表
单向链表是最简单的链表形式。我们将链表中最基本的数据称为节点(node),每一个节点包含了数据块和指向下一个节点的指针,链表有一个头指针变量,图中以head表示。可以看出,head指向第一个元素,第一个元素又指向第二个元素……直到最后一个元素,该元素不再指向其他元素,它称为表尾,它的地址部分为空,链表到此结束。

可以看到,要找链表中的某一元素,必须先找到上一个元素,根据它提供的下一个元素的地址才能找到下一个元素。如果不提供头指针,则整个链表都无法访问。链表如同一条铁链一样,一环扣一环,中间是不能断开的。
为了理解什么是链表,打一个通俗的比方:幼儿园的老师带领孩子们出来散步,老师牵着第一个小孩的手,第一个小孩的另一只手牵着第二个孩子……这就是一个链,最后一个孩子有一只手空着,他是链尾。要找到这个队伍,必须先找到老师,然后顺序找到每一个孩子。
变量声明:

const int maxn=1010;
struct node{    //point即指针,data就是需要维护的数据
    int point,data;
}a[maxn];
int head,cnt;    //head即头指针,cnt即内存池计数器

建立:

head=++cnt;        //把head设为没有实际意义的哨兵
a[head].data=0;

插入(插入数据now到第k个元素之后):

add(++k,now);    //进入,因为计算时考虑了哨兵,所以进入时++k
void add(int k,int now)
{
    for(int i=head;i;i=a[i].point)    //从头指针开始遍历链表
        if(!(--k))        //到达插入位置
        {
            a[++cnt].point=a[i].point;    //将新插入节点的指针指向插入位置的后继
            a[i].point=cnt;        //将前驱节点的指针指向新插入节点
            a[cnt].data=now;
            break;
        }
}


删除(删除第k个元素):

del(++k);    //进入
void del(int k)
{
    for(int i=head;i;i=a[i].point)
        if((--k)==1)    //找到前驱
        {
            a[i].point=a[a[i].point].point;        //将前驱的指针指向后继
            break;
        }
}


遍历链表:

for(int i=a[head].point;i;i=a[i].point)
    cout<<a[i].data<<endl;

2,双向链表
顾名思义,双向链表就是有两个方向的链表。同单向链表不同,在双向链表中每一个节点不仅存储指向下一个节点的指针,而且存储指向前一个节点的指针。它的优点是访问、插入、删除更方便。但“是以空间换时间”。

变量声明:

struct node{
    int pre,nxt,data;    //前驱和后继
}a[maxn];
int head,cnt;

插入:

void add(int k,int now)
{
    for(int i=head;i;i=a[i].nxt)
        if(!(--k))
        {
            a[++cnt].nxt=a[i].nxt;    //这两个和单链表一样
            a[i].nxt=cnt;
            a[a[cnt].nxt].pre=cnt;    //将后继的前驱更新为新插入节点
            a[cnt].pre=i;    //将新插入节点的前驱设为其前驱
            a[cnt].data=now;
            break;
        }
}


删除:

void del(int k)
{
    for(int i=head;i;i=a[i].nxt)
        if(!(--k))
        {
            a[a[i].pre].nxt=a[i].nxt;
            a[a[i].nxt].pre=a[i].pre;
            break;
        }
}

3,循环链表
(1),单向循环链表
最后一个节点的指针指向头结点
(2),双向循环链表
最后一个节点的指针指向头结点,且头结点的前驱指向最后一个结点
代码实现就不再给出,相信大家已经能够实现。

原文地址:https://www.cnblogs.com/ivanovcraft/p/9037475.html

时间: 2024-10-13 17:01:50

链表及数组模拟链表的相关文章

团体程序设计天梯赛-练习集 L2-2. 链表去重 数组模拟链表

L2-2. 链表去重 时间限制 300 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 给定一个带整数键值的单链表L,本题要求你编写程序,删除那些键值的绝对值有重复的结点.即对任意键值K,只有键值或其绝对值等于K的第一个结点可以被保留.同时,所有被删除的结点必须被保存在另外一个链表中.例如:另L为21→-15→-15→-7→15,则你必须输出去重后的链表21→-15→-7.以及被删除的链表-15→15. 输入格式: 输入第一行包含链表第一个结

【日常学习】【SPFA负环+数组模拟链表实现】codevs2645 Spore题解

之前刚刚写了一道"香甜的黄油",是USACO的经典题目了.那道题用SPFA怎么找都过不了,看着别人的PAS轻松过各种拙计.黄学长说最佳方案应当是堆优化的dij,我还没有血,等学了那个之后再写黄油题解吧. 题目: 题目描述 Description 在星系1 的某颗美丽的行星之上.某陈将去标号为N 的星系,从星系g1 到达g2,某陈需要花费c1 的代价[主要是燃料,另外还有与沿途Grox 的势力作战的花费],c1 小于0 则是因为 这样的星系旅行,会给某陈带来收益[来源于物流差价,以及一些

UVa12657 - Boxes in a Line(数组模拟链表)

题目大意 你有一行盒子,从左到右依次编号为1, 2, 3,…, n.你可以执行四种指令: 1 X Y表示把盒子X移动到盒子Y左边(如果X已经在Y的左边则忽略此指令).2 X Y表示把盒子X移动到盒子Y右边(如果X已经在Y的右边则忽略此指令).3 X Y表示交换盒子X和Y的位置.4 表示反转整条链. 盒子个数n和指令条数m(1<=n,m<=100,000) 题解 用数组来模拟链表操作,对于每个节点设置一个前驱和后继. 1操作是把x的前驱节点和x的后继节点连接,y节点的前驱和x节点连接,x节点和y

UVa 11988 数组模拟链表

题目:在一个没有显示器的电脑上输入一个字符串,键盘坏掉了,会随机的出现home,和end按键, 字符串中'['代表home键(句首),']'代表end键(句尾),问最后输出的字符串的格式. 分析:模拟屏幕操作,移动光标,模拟缓冲区输出操作. 说明:数组模拟链表操作,跟随链表操作,形象化模拟. 1 // UVa11988 Broken Keyboard 2 // Rujia Liu 3 #include<cstdio> 4 #include<cstring> 5 const int

B - Broken Keyboard (a.k.a. Beiju Text) 数组模拟链表

You're typing a long text with a broken keyboard. Well it's not so badly broken. The only problem with the keyboard is that sometimes the "home" key or the "end" key gets automatically pressed (internally). You're not aware of this iss

PAT 甲级 1052 Linked List Sorting (25 分)(数组模拟链表,没注意到不一定所有节点都在链表里)

1052 Linked List Sorting (25 分) A linked list consists of a series of structures, which are not necessarily adjacent in memory. We assume that each structure contains an integer key and a Next pointer to the next structure. Now given a linked list, y

UVA11988 Broken Keyboard (a.k.a. Beiju Text)【数组模拟链表】

Broken Keyboard (a.k.a. Beiju Text) You're typing a long text with a broken keyboard. Well it's not so badly broken. The only problem with the keyboard is that sometimes the "home" key or the "end" key gets automatically pressed (inter

josephus Problem 中级(使用数组模拟链表,提升效率)

问题描述: 在<josephus Problem 初级(使用数组)>中,我们提出了一种最简单直接的解决方案. 但是,仔细审视代码之后,发现此种方案的效率并不高,具体体现在,当有人出局时,遍历数组仍需要对其进行判断, 这无疑做了无用功,降低了代码效率,在人数多时尤其明显. 解决方案: 当有人出局时,考虑将当前出局的人的前一个人(未出局)的下一个人置为当前出局的下一个人(未出局).这样,便确保了每次对counter的增加都是有效的,遍历到的人都是还没有出局的.大大提升了程序的效率.这其实运用了链表

UVa 11988 (数组模拟链表) Broken Keyboard (a.k.a. Beiju Text)

题意: 模拟一个文本编辑器,可以输入字母数字下划线,如果遇到'['则认为是Home键,如果是']'则认作End键. 问最终屏幕上显示的结果是什么字符串. 分析: 如果在数组用大量的移动字符必然很耗时.所以next数组表示显示屏中s[i]右边的字符编号,变量cur模拟光标,即当前光标位于s[cur]的右边. 变量last记录显示屏最后一个字符的下标. 我理解的连接的情况应该是这样子的: 1 //#define LOCAL 2 #include <cstdio> 3 #include <cs