服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++如何用数组模拟链表

C++如何用数组模拟链表

2022-08-17 10:23Kicamon C/C++

大家好,本篇文章主要讲的是C++如何用数组模拟链表,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下

前言

链表是指由一系列储存在非连续储存空间 结点组成的储存结构。每个结点由两部分组成:一是储存元素的数据域,一是储存下一个节点地址的指针域。用数组模拟链表可以十分清晰明了地理解这一定义。

在这里,我们简单地介绍一下单链表和双链表两种链表以及用数组模拟实现它们的方式。

1.单链表

单链表是指针方向单向的链表,即a结点的指针域储存着b结点的地址,而b结点的指针域内没有储存a结点的地址。在访问时,可以由a到b访问,而不能由b到a访问。

C++如何用数组模拟链表

如图可以清晰地看到,各个结点的指向都是单向的。

Q: 那么,如何用数组来实现它呢?

A: 方法如下

在k结点右侧插入元素x。先将x赋值给该节点的数据域(e[idx]),然后将k结点的指针域赋值给该结点的指针域,最后将k结点的指针域储存的地址改为该节点的地址。

?
1
2
3
4
5
6
void add(int k, int x)
{
    e[idx] = x;
    ne[idx] = ne[k];
    ne[k] = idx++;
}
删除k结点指向的结点。这里所指的删除,是将k的指向改为该结点的指向。原本为a -> b -> c,改为a -> c,b结点依然存在,只是没有其他结点指向它,也就无法通过链表访问它,我们认为它就再链表上被删除了。
?
1
2
3
4
void remove(int k)
{
    ne[k] = ne[ne[k]];
}

读取链表。读取链表只用注意一点,在用单指针扫描时不是将指针位置右移,而是将指针移动到该结点指向的位置。

?
1
2
for (int i = head; i != -1; i = ne[i]) cout << e[i] << ' ';
cout << endl;

主要的操作就是如此,下边看看完整代码:

这是较为经典的写法,我个人认为有些麻烦,head不必单独拿出来写一个函数。但是有助于理解。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include<iostream>
using namespace std;
 
const int M = 1e5 + 10;
 
int m, k, x, idx, head;
int e[M], ne[M];
 
void init()
{
    head = -1, idx = 0;
}
 
void add_head(int x)
{
    e[idx] = x;
    ne[idx] = head;
    head = idx++;
}
 
void remove(int k)
{
    ne[k] = ne[ne[k]];
}
 
void add(int k, int x)
{
    e[idx] = x;
    ne[idx] = ne[k];
    ne[k] = idx++;
}
 
int main()
{
    init();
 
    cin >> m;
    while (m--)
    {
        char op;
        cin >> op;
 
        if (op == 'H')
        {
            cin >> x;
            add_head(x);
        }
        else if (op == 'D')
        {
            cin >> k;
            if (!k) head = ne[head];
            remove(k - 1);
        }
        else
        {
            cin >> k >> x;
            add(k - 1, x);
        }
    }
 
    for (int i = head; i != -1; i = ne[i]) cout << e[i] << ' ';
    cout << endl;
 
    return 0;
}

这种写法稍微简便一些,用a[0]替代head。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include<iostream>
using namespace std;
 
const int M = 1e5 + 10;
 
int m, k, x, idx, head;
int e[M], ne[M];
 
void init()
{
    ne[0] = -1, idx = 1;
}
 
void remove(int k)
{
    ne[k] = ne[ne[k]];
}
 
void add(int k, int x)
{
    e[idx] = x;
    ne[idx] = ne[k];
    ne[k] = idx++;
}
 
int main()
{
    init();
 
    cin >> m;
    while (m--)
    {
        char op;
        cin >> op;
 
        if (op == 'H')
        {
            cin >> x;
            add(0, x);
        }
        else if (op == 'D')
        {
            cin >> k;
            if (!k) head = ne[head];
            remove(k);
        }
        else
        {
            cin >> k >> x;
            add(k, x);
        }
    }
 
    for (int i = ne[0]; i != -1; i = ne[i]) cout << e[i] << ' ';
    cout << endl;
 
    return 0;
}

2.双链表

双链表顾名思义就是指针方向双向的链表。

C++如何用数组模拟链表

可以看到除了头尾他们的指针都是双向的。

它的实现方法如下:

创建开始和结束结点。0表示开始,1表示结束,互相指向,在插入时直接往中间插入即可。

?
1
2
3
4
5
void init()
{
    r[0] = 1, l[1] = 0;
    idx = 2;
}

插入结点。双链表插入结点的方法与单链表相同,但是操作要稍微复杂一些,这是在k结点右边插入一结点的代码。它要顾及结点左右的结点指向,对于两边都要操作。面临在k结点左边插入一结点时,不必单独在写一个函数,而改成在l[k]结点的右边插入一个结点。

?
1
2
3
4
5
6
7
void add(int k, int x)
{
    a[idx] = x;
    r[idx] = r[k], l[idx] = l[r[k]];
    l[r[k]] = idx, r[k] = idx;
    idx++;
}

删除节点。删除结点与插入结点同理,我就不多赘述了。

?
1
2
3
4
5
void remove(int k)
{
    r[l[k]] = r[k];
    l[r[k]] = l[k];
}

输出链表。可以选择输出方向,这里是从左往右输出。

?
1
2
for (int i = r[0]; i != 1; i = r[i])cout << a[i] << ' ';
    cout << endl;

以下是完整代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include<iostream>
using namespace std;
 
const int N = 1e5 + 10;
 
int a[N], l[N], r[N];
int idx;
int m;
 
void init()
{
    r[0] = 1, l[1] = 0;
    idx = 2;
}
 
void add(int k, int x)
{
    a[idx] = x;
    r[idx] = r[k], l[idx] = l[r[k]];
    l[r[k]] = idx, r[k] = idx;
    idx++;
}
 
void remove(int k)
{
    r[l[k]] = r[k];
    l[r[k]] = l[k];
}
 
int main()
{
    init();
    cin >> m;
    while (m--)
    {
        int k, x;
        string op;
        cin >> op;
        if (op == "L")
        {
            cin >> x;
            add(0, x);
        }
        else if (op == "R")
        {
            cin >> x;
            add(l[1], x);
        }
        else if (op == "D")
        {
            cin >> k;
            remove(k + 1);
        }
        else if (op == "IL")
        {
            cin >> k >> x;
            add(l[k + 1], x);
        }
        else if (op == "IR")
        {
            cin >> k >> x;
            add(k + 1, x);
        }
    }
 
    for (int i = r[0]; i != 1; i = r[i])cout << a[i] << ' ';
    cout << endl;
    return 0;
}

总结

到此这篇关于C++如何用数组模拟链表的文章就介绍到这了,更多相关C++数组模拟链表内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/Kicamon/article/details/122432389

延伸 · 阅读

精彩推荐
  • C/C++C++初阶之list的模拟实现过程详解

    C++初阶之list的模拟实现过程详解

    在C++中我们经常使用STL,那个在那些我们常用的数据结构vector,list的背后,又是如何实现的呢?这篇文章主要给大家介绍了关于C++初阶之list的模拟实现的相关资...

    qx LIU 20004352021-12-13
  • C/C++C中qsort快速排序使用实例

    C中qsort快速排序使用实例

    在学习C++ STL的sort函数,发现C中也存在一个qsort快速排序,要好好学习下C的库函数啊...

    C语言教程网11302021-01-13
  • C/C++C++实现LeetCode(28.实现strStr()函数)

    C++实现LeetCode(28.实现strStr()函数)

    这篇文章主要介绍了C++实现LeetCode(28.实现strStr()函数),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...

    Grandyang11752021-11-25
  • C/C++一文弄懂C语言如何实现单链表

    一文弄懂C语言如何实现单链表

    单链表是由多个结点链接组成,它的每个结点包含两个域,一个数据域和一个链接域(地址域),下面这篇文章主要给大家介绍了关于C语言如何实现单链表的相关...

    忱叁6232021-12-30
  • C/C++详解C++模板编程中typename用法

    详解C++模板编程中typename用法

    typename在C++类模板或者函数模板中经常使用的关键字,此时作用和class相同,只是定义模板参数,下面通过例子给大家介绍c++模板typename的具体用法,一起看...

    Erice_s11002021-11-22
  • C/C++windows下在vim中搭建c语言开发环境的详细过程

    windows下在vim中搭建c语言开发环境的详细过程

    这篇文章主要介绍了windows下在vim中搭建c语言开发环境,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    其铄7072021-11-05
  • C/C++C语言正则表达式详解 regcomp() regexec() regfree()用法详解

    C语言正则表达式详解 regcomp() regexec() regfree()用法详解

    C语言处理正则表达式常用的函数有regcomp()、regexec()、regfree()和regerror(),这里就为大家介绍一下,需要的朋友可以参考一下啊...

    C语言教程网8992021-06-23
  • C/C++C语言数据输入与输出实例详解

    C语言数据输入与输出实例详解

    这篇文章主要介绍了C语言数据输入与输出实例详解的相关资料,需要的朋友可以参考下...

    boy_cto_tony9332021-05-18