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

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

服务器之家 - 编程语言 - C/C++ - C++代码实现双向链表

C++代码实现双向链表

2022-12-09 13:25追梦的小年青 C/C++

这篇文章主要为大家详细介绍了C++代码实现双向链表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了C++实现双向链表的具体代码,供大家参考,具体内容如下

双向链表:两个指针域,一个指向前结点,一个指向后结点

list.h

?
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
#pragma once
#define OK         1
#define ERROR     0
#define TRUE     1
#define FALSE     0
 
typedef int Status;
typedef int ElemType;
 
typedef struct DNode
{
    struct DNode *prior;        //前结点指针域
    ElemType data;                //数据域
    struct DNode *next;            //后结点指针域
}DNode, *DLinkList;                //结点和指向结点的指针
 
bool InitDLinkList(DLinkList &L);                        //双链表初始化
Status CreatDLinkList(DLinkList &L);                    //尾插法创建链表,包含初始化功能
bool InsertNextDNode(DNode *p, DNode *s);                //结点s插入在结点p之后
Status DeleteNextDNode(DNode *p, ElemType &e);            //删除结点p的后继节点                
void ListTraverse(const DLinkList L);                    //双链表的遍历
Status ListInsert(DLinkList &L, int i, ElemType e);        //指定位置插入元素
Status ListDelete(DLinkList &L, int i, ElemType &e);    //指定位置删除元素
DNode* GetElem(DLinkList L, int i);                        //查找链表指定位置节点,返回的是结点
void DestoryList(DLinkList &L);                            //销毁双链表,需要释放头结点

oper_func.cpp

?
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <iostream>
#include"list.h"
 
bool InitDLinkList(DLinkList &L)
{
    //构建空的双链表,作为双链表的头结点,数据域为空
    L = new DNode;
    if (L == NULL)                //内存分配失败
        return FALSE;
    L->prior = NULL;            //头结点的前驱指针始终指向NULL    
    L->next = NULL;                //暂时指向NULL
    return TRUE;
}
 
Status CreatDLinkList(DLinkList &L)
{
    //利用InsertNextDNode函数来创建
 
    using std::cin;
    using std::cout;
    using std::endl;
    if (InitDLinkList(L))
    {
        DNode *s,*r = L;                //s为新建的新结点,用来存储数据,而r为尾指针,始终指向尾部节点
        int num;
        cout << "输入你需要创建的双链表的个数:";
        cin >> num;
        for (int i = 1; i <= num; i++)
        {
            s = new DNode;                //创建的新结点
            cout << "输入第" << i << "个元素:";
            cin >> s->data;                //输入数据
            s->next = NULL;
            InsertNextDNode(r,s);        //结点s插在尾部节点之后
            r = s;                        //尾指针指向新的尾结点
        }
        return OK;
    }
    else
    {
        cout << "内存不够,单链表创建失败!" << endl;
        return ERROR;
    }
}
 
//结点s插入在结点p之后
bool InsertNextDNode(DNode *p, DNode *s)
{
    if (p == NULL || s == NULL)
        return FALSE;            //非法参数
    s->next = p->next;
    if (p->next != NULL)        //如果p不是最后一个结点
    {
        p->next->prior = s;
    }
    s->prior = p;
    p->next = s;
    return TRUE;
}
 
Status DeleteNextDNode(DNode *p, ElemType &e)
{
    if(p == NULL)
        return FALSE;            //非法参数
    DNode *q = p->next;            //找到p节点的后继节点
    if (q == NULL)                //节点p没有后继节点
    {
        return ERROR;
    }
    else
    {
        //有后继节点,但是p的后继节点为空
        p->next = q->next;
        e = q->data;
        if (q->next != NULL)
        {
            q->next->prior = p;
        }
        delete q;
        return OK;
    }
}
 
void ListTraverse(const DLinkList L)
{
    using std::cout;
    using std::endl;
    int i = 1;
    DNode *p = L->next;                    //指向第一个元素
    if (p == NULL)
    {
        cout << "双链表为空,无法输出元素!" << endl;
        return;
    }
    while (p)
    {
        cout << "第" << i++ << "个元素为:" << p->data << endl;
        p = p->next;
    }
}
 
Status ListDelete(DLinkList &L, int i, ElemType &e)
{
    if (i < 1)                 //位置不合理
        return ERROR;
    //寻找第i-1个结点
    DNode *p = GetElem(L, i - 1);
    //删除i-1结点的后面结点
    return DeleteNextDNode(p,e);
}
 
DNode* GetElem(DLinkList L, int i)
{
    DNode *p = L;
    int j = 0;                //表示p指向的当前结点的位置,此时为头结点
    while (p != NULL && j < i)
    {
        p = p->next;        //指向下一个结点
        j++;
    }
    return p;
}
 
void DestoryList(DLinkList &L)
{
    using std::cout;
    using std::endl;
    ElemType temp;
    int i = 1;
    while (L->next != NULL)
    {
        DeleteNextDNode(L,temp);
        cout << "第" << i++ << "个删除的元素为:" << temp << endl;
    }
    cout << "双链表全部数据销毁成功!" << endl;
    delete L;
    cout << "头结点销毁,整个双链表销毁成功!" << endl;
    L = NULL;                //头指针指向NULL
}
 
Status ListInsert(DLinkList &L, int i, ElemType e)
{
    if (i < 1)
        return FALSE;
    //寻找第i-1个结点
    DNode *p = GetElem(L, i - 1);
    //直接在i-1结点的后面插入元素即可
    DNode *s = new DNode;        //新建节点
    s->data = e;
    s->next = NULL;
    s->prior = NULL;
    return InsertNextDNode(p,s);
}

main.cpp

?
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/* 双向链表:带头结点,且头结点的prior指针时钟指向为NULL
 
1、双链表的初始化
2、双链表的创建
3、双链表的结点插入(相当于后插操作):(结点s插入结点p之后)需要考虑p结点是不是最后一个结点
    如果想前插操作,则找到该节点的i-1节点,然后实行后插操作也是一样
4、双链表的结点删除(相当于后删操作):(删除p节点的后序节点q)需要考虑p结点是不是最后一个结点
    也要考虑q节点是不是最后一个结点
5、双链表的删除:
6、双链表的遍历:
7、双链表的销毁:需要回收头结点
 
*/
 
#include <iostream>
#include"list.h"
 
void showMenu()
{
    using std::cout;
    using std::cin;
    using std::endl;
    cout << "*********************************************************" << endl;
    cout << "*** 1.指定位置插入元素            2.删除指定位置元素 ***" << endl;
    cout << "*** 3.遍历单链表            0.销毁双链表并退出 ***" << endl;
    cout << "*********************************************************" << endl;
}
 
int main()
{
    using std::cout;
    using std::cin;
    using std::endl;
    int select = 0, flag = -1;            //输入的选择
 
    DLinkList L;                //L表示头指针,始终指向表头
 
    if (CreatDLinkList(L))        //尾插法创建单链表
    {
        cout << "双链表创建成功!" << endl;
    }
    else
        cout << "双链表创建失败!" << endl;
 
    while (true)
    {
        showMenu();
        cout << "输入你的选择:";
        cin >> select;
        switch (select)
        {
        case 1: {        //指定位置插入元素
            int position = 0, elem = 0;
            cout << "输入插入的位置和元素:";
            cin >> position >> elem;
            if (ListInsert(L, position, elem))
                cout << "指定位置插入元素成功!" << endl;
            else
                cout << "内存分配失败或者插入位置越界,插入失败!" << endl;
        }
                break;
        case 2: {        //删除指定位置节点
            int position = 0, elem = 0;
            cout << "输入指定位置:";
            cin >> position;
            if (ListDelete(L, position, elem))
            {
                cout << "删除指定位置元素成功!元素为:" << elem << endl;
            }
            else
            {
                cout << "单链表为空或者删除位置不合理!" << endl;
            }
        }
                break;
        case 3: {
            ListTraverse(L);
        }
                break;
        case 0: {
            DestoryList(L);
            system("pause");
            return 0;
        }
        break;
        }
    }
    return 0;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/qq_33373460/article/details/124498538

延伸 · 阅读

精彩推荐
  • C/C++C语言 strftime 格式化显示日期时间的实现

    C语言 strftime 格式化显示日期时间的实现

    下面小编就为大家带来一篇C语言 strftime 格式化显示日期时间的实现。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看...

    C语言教程网10822021-04-25
  • C/C++C语言中怎么在main函数开始前执行函数

    C语言中怎么在main函数开始前执行函数

    C语言中怎么在main函数开始前执行函数呢?下面小编就大家详细的介绍一下。需要的朋友可以过来参考下,希望对大家有所帮助...

    C语言教程网9742021-01-05
  • C/C++使用C语言操作文件的基本函数整理

    使用C语言操作文件的基本函数整理

    这篇文章主要介绍了使用C语言操作文件的基本函数整理,包括创建和打开以及关闭文件的操作方法,需要的朋友可以参考下...

    C语言教程网9972021-03-09
  • C/C++进程间通信之深入消息队列的详解

    进程间通信之深入消息队列的详解

    本篇文章是对消息队列的应用进行了详细的分析介绍,需要的朋友参考下...

    C语言教程网6732020-12-08
  • C/C++C++实现猴子吃桃的示例代码

    C++实现猴子吃桃的示例代码

    这篇文章主要介绍了C++实现猴子吃桃的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面...

    Rage Your Dream.DS10082021-08-19
  • C/C++C语言实现链队列基本操作

    C语言实现链队列基本操作

    这篇文章主要为大家详细介绍了C语言实现链队列基本操作,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    似曾不相识9362022-01-11
  • C/C++C语言进阶教程之函数指针详解

    C语言进阶教程之函数指针详解

    函数指针是一个指针变量,它可以存储函数的地址,然后使用函数指针,下面这篇文章主要给大家介绍了关于C语言进阶教程之函数指针的相关资料,需要的朋友...

    白杨Cc6502022-11-15
  • C/C++QT实现简单计算器功能

    QT实现简单计算器功能

    这篇文章主要为大家详细介绍了QT实现简单计算器功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    Frank Kong10132022-11-17