持续创作,加速成长!这是我参与「掘金日新计划 · 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;
}