C++代码实现双向链表

 更新时间:2022年5月26日 20:09  点击:272 作者:追梦的小年青

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

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

list.h

#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

#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

/* 双向链表:带头结点,且头结点的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

[!--infotagslink--]

相关文章

  • C++ STL标准库std::vector的使用详解

    vector是表示可以改变大小的数组的序列容器,本文主要介绍了C++STL标准库std::vector的使用详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2022-03-06
  • C++中取余运算的实现

    这篇文章主要介绍了C++中取余运算的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
  • 详解C++ string常用截取字符串方法

    这篇文章主要介绍了C++ string常用截取字符串方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • C++调用C#的DLL程序实现方法

    本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
  • C++中四种加密算法之AES源代码

    本篇文章主要介绍了C++中四种加密算法之AES源代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...2020-04-25
  • C++ 整数拆分方法详解

    整数拆分,指把一个整数分解成若干个整数的和。本文重点给大家介绍C++ 整数拆分方法详解,非常不错,感兴趣的朋友一起学习吧...2020-04-25
  • C++中 Sort函数详细解析

    这篇文章主要介绍了C++中Sort函数详细解析,sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变...2022-08-18
  • C++万能库头文件在vs中的安装步骤(图文)

    这篇文章主要介绍了C++万能库头文件在vs中的安装步骤(图文),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
  • 详解C++ bitset用法

    这篇文章主要介绍了C++ bitset用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • 浅谈C++中的string 类型占几个字节

    本篇文章小编并不是为大家讲解string类型的用法,而是讲解我个人比较好奇的问题,就是string 类型占几个字节...2020-04-25
  • C++ Eigen库计算矩阵特征值及特征向量

    这篇文章主要为大家详细介绍了C++ Eigen库计算矩阵特征值及特征向量,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
  • VSCode C++多文件编译的简单使用方法

    这篇文章主要介绍了VSCode C++多文件编译的简单使用方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-03-29
  • C++ pair的用法实例详解

    这篇文章主要介绍了C++ pair的用法实例详解的相关资料,需要的朋友可以参考下...2020-04-25
  • C++中的循环引用

    虽然C++11引入了智能指针的,但是开发人员在与内存的斗争问题上并没有解放,如果我门实用不当仍然有内存泄漏问题,其中智能指针的循环引用缺陷是最大的问题。下面通过实例代码给大家介绍c++中的循环引用,一起看看吧...2020-04-25
  • C++随机点名生成器实例代码(老师们的福音!)

    这篇文章主要给大家介绍了关于C++随机点名生成器的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • C++如何删除map容器中指定值的元素详解

    map容器是C++ STL中的重要一员,删除map容器中value为指定元素的问题是我们经常与遇到的一个问题,下面这篇文章主要给大家介绍了关于利用C++如何删除map容器中指定值的元素的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。...2020-04-25
  • C++ 约瑟夫环问题案例详解

    这篇文章主要介绍了C++ 约瑟夫环问题案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...2021-08-15
  • C++中cin的用法详细

    这篇文章主要介绍了C++中cin的用法详细,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • 基于C++中常见编译错误的总结详解

    本篇文章是对C++中的常见编译错误进行了详细的分析介绍,需要的朋友参考下...2020-04-25
  • c++优先队列(priority_queue)用法详解

    这篇文章主要介绍了c++优先队列(priority_queue)用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25