22计算机408考研—数据结构—双向循环链表

100 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

2022计算机考研408—数据结构—线性表、栈、队列、数组 手把手教学考研大纲范围内的线性表、栈、队列、数组 22考研大纲数据结构要求的是C/C++,笔者以前使用的都是Java,对于C++还很欠缺, 如有什么建议或者不足欢迎大佬评论区或者私信指出

Talk is cheap. Show me the code. 理论到处都有,代码加例题自己练习才能真的学会

双向循环链表

双向循环链表和单链表也是大致相同的
只是在修改结点的关系的时候需要修改每个结点的前后节点
//循环链表
#include "iostream"
#include "vector"

using namespace std;

typedef struct DuLNode {    //结点,每个结点有一个值,
    int data;               //每个结点包括两个指针,一个指向前一个结点,一个指向后一个结点
    struct DuLNode *prior;  //指定当前结点的前一个结点
    struct DuLNode *next;   //指定当前结点的后一个结点
} DuLNode, *DuLinkList;

bool ListInitDul(DuLinkList &L, vector<int> data) { //初始化双指针循环链表
    DuLNode *headL = new DuLNode;   //记录一下头结点,初始化结束后,把头结点重新赋值给L
    DuLNode *node = new DuLNode;    //初始化的时候,把第一个值给node,依次向下连接
    node->data = data[0];
    L = node;
    headL = L;
    for (int i = 1; i < data.size(); i++) {
        DuLNode *temp = new DuLNode;
        temp->data = data[i];   //每次创建一个新的结点,当作node的下一个,绑定与node的关系
        node->next = temp;      //绑定temp变成node的下一个
        temp->prior = node;     //绑定node变成temp的上一个
        node = temp;    //绑定后,把当前点给node, 方便下次循环绑定下一个值
    }
    node->next = L; //node此时为最后一个值,,node的下一个绑定头结点(循环链表)
    L->prior = node;    //L的前一个为node,首结点的上一个就是当前链表的最后一个
    L = headL;  //把初始头结点给L
    return true;
}

bool ListGetDulElem(DuLinkList L, int index, DuLNode &node) {   //得到链表序列为index的值,传给node
    int j = 1;
    while (L && j < index) {    //找到序列为index的结点,
        L = L->next;            //前面有几个,就循环几次,每次都向下走一位
        j++;
    }
    if (!L) {   //如果L为空,直接跳过
        return false;
    }
    node = *L;  //如果不为空,把当前结点传给node
    return true;
}

bool ListInsertDul(DuLinkList &L, int index, int data) {    //在序列index位置插入结点
    DuLNode *node = new DuLNode;
    if (!ListGetDulElem(L, index, *node)) { //查找一下指定index位置,如果没有当前位置,返回false
        return false;
    }
    //假设在a b的位置插入c(在a b中间插入c,b为node,c为newNode)
    //设置c的前一个为a      设置a的下一个为c    设置c的下一个为b    设置b的上一个为c
    DuLNode *newNode = new DuLNode;
    newNode->data = data;
    newNode->prior = node->prior;   //把node的前一个给newNode的前一个,
    node->prior->next = newNode;    //把newNode给node的前一个的后一个
    newNode->next = node;           //把node给newNode的下一个
    node->prior = newNode;          //把newNode给node的前一个
    if (index == 1) {   //如果是插入第一个的话,返回node的上一个
        L = node->prior;    //node此时为第二个,新插入的为第一个值,把第一个值给L
    }
    return true;
}

bool ListDeleteDul(DuLinkList &L, int index) {  //删除序列为index的值
    DuLNode *headL = new DuLNode;
    headL = L;
    DuLNode *node = new DuLNode;
    if (!ListGetDulElem(L, index, *node)) { //找到序列index的结点,传给node
        return false;
    }
    //删除node(node为序列index的结点)
    //假设a b c删除 b   (b为node)
    //设置a的下一个为c     设置c的上一个为a
    node->prior->next = node->next;
    node->next->prior = node->prior;
    return true;
}

void ListPrintDul(DuLinkList L) {   //输出循环节点
    if (L == NULL) {
        return;
    }
    DuLNode *headL = new DuLNode;   //保存头结点,头结点用来判断是不是已经输出过了
    headL = L;
    do {                            //循环输出
        cout << L->data << " ";
        L = L->next;
    } while (L->next != headL->next);   //判断是不是和头结点的下一个相等,如果相等说明已经输出过了
    cout << "\n";                       //这里有个小bug,如果用L和headL直接比较,相同的结点会显示不同的地址,导致 一直在输出
}                                       //(在线等大佬解决,评论私信指出都可以)

int main() {
    DuLinkList LinkList;
    vector<int> data = {1, 2, 3, 4, 5, 6};
    ListInitDul(LinkList, data);    //把vector传入循环链表
    ListInsertDul(LinkList, 1, -1);
    ListInsertDul(LinkList, 4, 8);
    ListInsertDul(LinkList, 7, 7);
    ListInsertDul(LinkList, 2, 4);
    ListPrintDul(LinkList);
    ListDeleteDul(LinkList, 2); //删除序列号为2的结点
    ListPrintDul(LinkList);
    DuLNode node;
    ListGetDulElem(LinkList, 2, node);  //得到序列号index的结点
    cout << node.data << "\n";
    return 0;
}

在这里插入图片描述