IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 数据结构【双向循环链表】 -> 正文阅读

[数据结构与算法]数据结构【双向循环链表】

双向循环链表:

数据结构示意图1.1.1如下:
在这里插入图片描述

图1.1.1 链表节点结构示意图

让代码来讲话吧:

Structure.h

#ifndef DATA_STRUCTURE_DCNLIST_STRUCTURE_H
#define DATA_STRUCTURE_DCNLIST_STRUCTURE_H
#include <iostream>

using namespace std;
/*-------------------1.链表----------------------*/
#define Mark 0                     //宏定义链表Mark的起始值,更改此处会产生联动效果
#define HeadM pHead->mark = Mark   //设置链表头结点pHead的mark为0
// (1)单向链表:
// (2)单向循环链表:
typedef struct SCNode {
    int date;           //数据
    unsigned int mark;  //第mark个节点
    SCNode *pNext;      //节点尾指针
} SN,                   //单向
SCN;                    //单向循环
//二者数据结构相同
//=============================================//
// (3)双向链表:
// (4)双向循环链表:
typedef struct DCNode {
    int date;           //数据
    unsigned int mark;  //第mark个节点
    DCNode *pPrev;       //节点头指针
    DCNode *pNext;       //节点尾指针
} DN,                   //双向
DCN;                    //双向循环
//二者数据结构相同
/*-------------------1.链表----------------------*/
#endif //DATA_STRUCTURE_DCNLIST_STRUCTURE_H

Structure.cpp


//
// Created by Today me on 2021/7/13.
//

#include "Structure.h"
#include "Operation.h"

/*-------------------1.链表----------------------*/
// (3)双向链表:
//遍历整个链表,返回尾节点
DCN *FindTail(DCN *pHead) {
    DCN *pNTemp = pHead;
    while (pHead->pNext != pNTemp)pHead = pHead->pNext;
    return pHead;
}

//查找任意节点[调用此函数前,需确保List中mark的顺序性]
DCN *FindNode(DCN *pHead, int pos) {
    while (pos-Mark != pHead->mark) {
        pHead = pHead->pNext;
    }
    return pHead;
}

//规律化NODE[mark]
DCN *RegularMark(DCN *pHead) {
    DCN *pNTemp = pHead;
    int count = Mark;
    do {
        pHead->mark = count++;
    }while (pNTemp!= (pHead = pHead->pNext));
    return pNTemp;
}
/*-------------------1.链表----------------------*/

Operation.h


//
// Created by Today me on 2021/7/13.
//

#ifndef DATA_STRUCTURE_DCNLIST_OPERATION_H
#define DATA_STRUCTURE_DCNLIST_OPERATION_H

#include "Structure.h"
/*-------------------1.链表----------------------*/

// (1)单向链表:
//  a.创建链表:
//  b.插入节点:1.头插     2.尾插    3.中间插
//  c.删除节点:1.头删     2.尾删    3.中间删
//  d.打印链表:
// (2)单向循环链表:
//  a.创建链表:
//  b.插入节点:1.头插     2.尾插    3.中间插
//  c.删除节点:1.头删     2.尾删    3.中间删
//  d.打印链表:
//=============================================//
// (3)双向链表:
//  a.创建链表:
//  b.插入节点:1.头插     2.尾插    3.中间插
//  c.删除节点:1.头删     2.尾删    3.中间删
//  d.打印链表:

// (4)双向循环链表:
DCN *FindTail(DCN *pHead);                //遍历整个链表,返回尾节点
DCN *FindNode(DCN *pHead, int pos);       //查找任意节点[调用此函数前,需确保List中mark的顺序性]
DCN *RegularMark(DCN *pHead);             //规律化NODE[mark]
//  a.创建链表:
DCN *CreateHead();

//  b.插入节点:1.头插     2.尾插    3.中间插
DCN *InsertHead(DCN *pHead);              //1.头插
DCN *InsertTail(DCN *pHead);              //2.尾插
DCN *InsertMiddle(DCN *pHead, int pos);    //3.中间插

//  c.删除节点:1.头删     2.尾删    3.中间删
DCN *DeleteHead(DCN *pHead);              //1.头插
DCN *DeleteTail(DCN *pHead);              //2.尾插
DCN *DeleteMiddle(DCN *pHead, int pos);    //3.中间插

//  d.打印链表:先正序输出,后逆序输出链表[以pNext方向为正,pPrev方向为逆向]
unsigned int DisplayList(DCN *pHead);
/*-------------------1.链表----------------------*/
#endif //DATA_STRUCTURE_DCNLIST_OPERATION_H


Operation.cpp

//
// Created by Today me on 2021/7/13.
//

#include "Operation.h"
/*-------------------1.链表----------------------*/
// (1)单向链表:
//  a.创建链表:
//  b.插入节点:1.头插     2.尾插    3.中间插
//  c.删除节点:1.头删     2.尾删    3.中间删
//  d.打印链表:

// (2)单向循环链表:
//  a.创建链表:
//  b.插入节点:1.头插     2.尾插    3.中间插
//  c.删除节点:1.头删     2.尾删    3.中间删
//  d.打印链表:

// (3)双向链表:

/*在此注释中以pNext方向为向后;
 * 以pPrev方向为向前。
 * */

//  a.创建链表:
//  b.插入节点:1.头插     2.尾插    3.中间插
//  c.删除节点:1.头删     2.尾删    3.中间删
//  d.打印链表:

// (4)双向循环链表:

/*在此注释中以pNext方向为向后;
 * 以pPrev方向为向前。
 * */

//  a.创建链表:
DCN *CreateHead() {
    DCN *pHead = new DCNode();
    pHead->pNext = pHead;     //节点尾指向自己pHead[循环]
    pHead->pPrev = pHead;     //节点头指向自己pHead[循环]
    HeadM;                      //设置HeadMark
    cout << "Enter a value of the ListHead[" << pHead->mark << "]:" << endl;
    cin >> pHead->date;         //键入头结点存储数据
    return pHead;
}

//  b.插入节点:1.头插     2.尾插    3.中间插
DCN *InsertHead(DCN *pHead) {
    DCN *LTail = FindTail(pHead);
    int TpMark = pHead->mark;
    char ch = 'y';
    while ('y' == ch || 'Y' == ch) {
        DCN *newNode = new DCNode();
        //if (nullptr == newNode){perror("内存申请失败");exit(-1);}
        cout << "Enter a value of the node[" << ++TpMark << "]:" << endl;
        newNode->mark = TpMark;      //设置newNode的mark
        cin >> newNode->date;        //键入存储的值

        pHead->pPrev = newNode;      //[内部]使原链表头的pPrev指针指向newNode[将NewNode插入pHead前,链接好向前的结构]
        newNode->pNext = pHead;      //[内部]使NewNode的尾指针pNext指向pHead[将NewNode插入pHead前,链接好向后的结构]

        newNode->pPrev = LTail;      //[外部]使NewNode的pPrev指针指向链表尾节点LTail[LTail与NewNode通过pPrev链接,构成向前环结构]
        LTail->pNext = newNode;      //[外部]使链表尾节点LTail的尾指针pNext指向NewNode[LTail与NewNode通过pNext链接,构成向后环结构]
        pHead = newNode;             //将NewNode赋值给pHead[前移指针pHead,保证pHead始终指向链表头]

        cout << "Enter choice inserter(y/n):" << endl;
        cin >> ch;
    }
    //RegularMark(pHead);
    return pHead;
}

DCN *InsertTail(DCN *pHead) {
    DCN *LTail = pHead;
    char ch = 'Y';
    LTail = FindTail(LTail);       //调用FindTail找到尾节点指针,赋给LTail
    int TpMark = LTail->mark;      //记录尾节点Mark
    while (ch == 'y' || ch == 'Y') {
        DCN *newNode = new DCNode();
        //if (nullptr == newNode){perror("内存申请失败");exit(-1);}
        cout << "Enter a value of the node[" << ++TpMark << "]:" << endl;
        newNode->mark = TpMark;     //写入TpMark到newNode Mark中
        cin >> newNode->date;

        LTail->pNext = newNode;     //[内部]将尾节点LTail的pNext指针指向NewNode[链接NewNode到List尾部,链接好向后的结构]
        newNode->pPrev = LTail;     //[内部]将新节点newNode的pPrev指针指向LTail[链接NewNode到List尾部,链接好向前的结构]

        newNode->pNext = pHead;     //[外部]使NewNode的尾指针pNext指针指向链表头节点pHead[pHead与NewNode通过pHead的pPrev链接,构成向后环结构]
        pHead->pPrev = newNode;     //[外部]使链表头节点pHead的头指针pPrev指向NewNode[pHead与NewNode通过NewNode的pNext链接,构成向前环结构]
        LTail = newNode;            //将NewNode赋给LTail[使LTail始终指向尾节点]

        cout << "Enter choice inserter(y/n):" << endl;
        cin >> ch;
    }
    //RegularMark(pHead);
    return pHead;
}

DCN *InsertMiddle(DCN *pHead, int pos) {
    DCN *pNTemp01 = pHead, *pNTemp02 = nullptr;
    pos--;
    char ch = 'y';
    //int count = 0;
    RegularMark(pHead);
    pNTemp01 = FindNode(pNTemp01, pos);    // 找到插入节点的前一个节点pNTemp01
    pNTemp02 = pNTemp01->pNext;         // 找到应该插入的位置节点pNTemp02
    while (ch == 'y' || ch == 'Y') {
        DCN *newNode = new DCNode();
        //if (nullptr == newNode){perror("内存申请失败");exit(-1);}
        newNode->mark = pNTemp01->mark;
        newNode->mark++;
        cout << "Enter a value of the inserted node:" << endl;
        cin >> newNode->date;
        pNTemp01->pNext = newNode;      // 将前节点pNTemp01的pNext指针指向新节点newNode[链接NewNode到pNTemp01后,链接好向后的结构]
        newNode->pPrev = pNTemp01;      // 将新节点newNode的pPrev指针指向前节点pNTemp01[链接NewNode到pNTemp01后,链接好向前的结构]
        newNode->pNext = pNTemp02;      // 将pNTemp02赋给newNode->pNext[将pNTemp02链接在newNode后]
        pNTemp02->pPrev = newNode;      // 将newNode赋给pNTemp02->pPrev[将newNode链接在pNTemp02前]
        pNTemp01 = pNTemp01->pNext;     // 将pNTemp01后移一位指向newNode
        //while (nullptr != (pNTemp01 = pNTemp01->pNext))++pNTemp01->mark;
        cout << "Enter choice of inserter(y/n):" << endl;
        cin >> ch;
        //count++;
    }
    //while (nullptr != (pNTemp01 = pNTemp01->pNext))pNTemp01->mark += count;
    RegularMark(pHead);
    return pHead;
}

//  c.删除节点:1.头删     2.尾删    3.中间删
DCN *DeleteHead(DCN *pHead) {
    char ch = 'y';
    DCN *pNTemp = pHead, *LTail = pHead->pPrev;
    while ('y' == ch || 'Y' == ch) {
        pNTemp = pHead;         //暂存pHead
        pHead = pHead->pNext;   //将pHead指向下一个节点
        pHead->pPrev = LTail;   //链接头尾
        LTail->pNext = pHead;   //链接尾头
        cout << "Enter choice of deleting head node (y/n):" << endl;
        cin >> ch;
        if (pHead != LTail) {      //确保DisplayList函数正常调用
            DisplayList(pHead);
            delete pNTemp;         //释放内存
        } else {
            cout << "Can't remove the last node!" << endl;
            return pHead;
        }
    }
    //RegularMark(pHead);
    return pHead;
}

DCN *DeleteTail(DCN *pHead) {     //(1)不断循环寻找最后节点删除
    //(1)
    char ch = 'y';
    DCN *pNTemp = nullptr, *LTail = pHead->pPrev, *pNTemp01 = nullptr;
    RegularMark(pHead);
    while ('y' == ch || 'Y' == ch) {
        pNTemp01 = LTail->pPrev;            // 找到尾节点的前一个节点
        pNTemp = LTail;                     // 暂存尾节点
        pNTemp01->pNext = pHead;            // 使得原尾节点前一个节点变为尾节点[尾首相连]
        pHead->pPrev = pNTemp01;            // 使得原尾节点前一个节点变为尾节点[首尾相连]
        //delete pNTemp;                      // 释放原尾节点内存
        cout << "Enter choice of deleting tail node (y/n):" << endl;
        cin >> ch;
        if (pHead != LTail) {       //确保DisplayList函数正常调用
            DisplayList(pHead);
            LTail = LTail->pPrev;   //偏移LTail,始终指向最新的尾节点
            delete pNTemp;          //释放内存
        } else {
            cout << "Can't remove the last node!" << endl;
            return pHead;
        }
    }
    //RegularMark(pHead);
    return pHead;
}

DCN *DeleteMiddle(DCN *pHead, int pos) {
    DCN *pNTemp01 = pHead, *pNTemp02 = nullptr, *pNTemp03 = nullptr;
    pNTemp01 = FindNode(pNTemp01, pos - 2);     // 前节点指针
    pNTemp02 = pNTemp01->pNext;                      // 中结点指针
    pNTemp03 = pNTemp02->pNext;                      // 尾结点指针
    pNTemp01->pNext = pNTemp03;         // 前后链接
    pNTemp03->pPrev = pNTemp01;         // 后前连接
    delete pNTemp02;                    // 删除中间节点
    pNTemp02 = nullptr;                 // 避免pNTemp02野指针
    //RegularMark(pHead);
    return pHead;
}

//  d.打印链表:
unsigned int DisplayList(DCN *pHead) {
    DCN *LTail = FindTail(pHead), *pNTemp = pHead;
    unsigned int count = 0;
    cout << "Forward display list:" << endl;
    do {
        cout << "NODE[" << pHead->mark << "] = " << pHead->date << endl;\
        pHead = pHead->pNext;
        count++;
    } while (pHead != LTail->pNext);
    cout << "\nInverted display list:" << endl;
    do {
        cout << "NODE[" << LTail->mark << "] = " << LTail->date << endl;
        LTail = LTail->pPrev;
    } while (LTail != pNTemp->pPrev);
    return count;
}

main.cpp

#include "Structure.h"
#include "Operation.h"

int main() {
    DCN *pHead = nullptr;               //创建单向链表类型的头指针pHead,初始化为空指针nullptr
    pHead = CreateHead();               //创建头结点,pHead存储头结点的位置(存储头结点的位置)
//    pHead = InsertHead(pHead);        //调用头插
    pHead = InsertTail(pHead);        //调用尾插
//    pHead = InsertMiddle(pHead,2);    //调用中间插入
//    pHead = DeleteHead(pHead);        //调用头删
//    pHead = DeleteTail(pHead);        //调用尾删
    pHead = DeleteMiddle(pHead,2);    //调用中间删除[至少三个节点]

    unsigned int count = DisplayList(pHead);
    cout << "\nCount of list = " << count << "\nThe tail date of list = " << FindTail(pHead)->date << endl;
    if (pHead!= nullptr)delete pHead;       //释放pHead
    return 0;
}


测试结果如下图1.1.2:
在这里插入图片描述
图1.1.2 测试结果

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-14 23:11:55  更:2021-07-14 23:14:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 16:55:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码