22计算机408考研—数据结构—线性表、栈、队列、数组

article/2025/11/6 7:33:58

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

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

顺序表
链表
双向循环链表 后面附:顺序表链表区别

栈实现括号问题
循环链栈表
递归斐波那契
递归汉诺塔
循环队列
链队(链式队列)

顺序表

官方含义:一段地址连续的存储单元依次存储线性表的数据元素。
其实就相当于数组,`把顺序表当数组看`最简单了
  // 顺序表#include <iostream>
#include "string.h"
#define MAXSIZE 1001using namespace std;typedef struct {    //定义学生结构体,包含学号和姓名char ID[20];char name[50];
} Student;typedef struct {    //定义线性表,和长度属性Student *elem;int length;
} StuList;bool ListInit(StuList &L) { //初始化线性表L.elem = new Student[MAXSIZE];  //给数组分配空间长度if (!L.elem) {  //如果没分配成功,就返回失败return false;}L.length = 0;   //初始化线性表后长度为0return true;
}//插入的时候需要注意把这一位后面的,每个都后移一位,然后把数据放到空出来的那位
bool ListInsert(StuList &L, int i, Student stu) {   //把Student类型插入到序列为i的位置if (i < 0 || i > L.length + 1) {    //判断插入位置是否正确return false;}if (L.length == MAXSIZE) {  //如果插入位置到达最大值,无法插入return false;}for (int j = L.length - 1; j >= i - 1; j--) {   //把i以后元素都向后移动一位,L.elem[j + 1] = L.elem[j];}L.elem[i - 1] = stu;    //把将要插入的放到指定位置++L.length;             //线性表长度+1return true;
}
//也是和插入的时候一样,把i后面的都向前移动一位
bool ListDelete(StuList &L, int i) {    //删除序列为i的元素if (i < 1 || i > L.length) {return false;}for (int j = i; j < L.length; j++) {    //把序列i以后的元素全部前移一位,盖住了序列为i的那位L.elem[j - 1] = L.elem[j];}--L.length;     //线性表长度-1return true;
}bool ListGetStu(StuList &L, int i, Student &s) {    //返回序列为i的元素if (i < 1 || i > L.length) {return false;}s = L.elem[i - 1];return true;
}int ListGetIndex(StuList &L, Student s) {   //找到与s相等的元素的下标for (int i = 0; i < L.length; i++) {if (strcmp(L.elem[i].ID , s.ID) && strcmp(L.elem[i].name , s.name)) {return i + 1;}}return 0;
}void ListMerge(StuList &A, StuList B) { //把B表中A表没有的元素插入到A表后面int a = A.length, b = B.length;for (int i = 0; i < B.length; i++) {if (!ListGetIndex(A, B.elem[i])) {  //A表中是否存在B.elem[i]ListInsert(A, ++a,B.elem[i]);}}A.length = a;   //a代表新线性表的大小,初始为A线性表大小,后面每次插入到A线性表一个值,a++
}void ListaddAll (StuList &A, StuList B) {   //把B线性表插入到A线性表后面int a = A.length, b = B.length;for (int i = 0; i < B.length; i++) {ListInsert(A, ++a,B.elem[i]);}A.length = a;
}int main() {StuList demo;ListInit(demo);Student student = {"123", "张三"};Student student2 = {"456", "李三"};ListInsert(demo, 1, student);ListInsert(demo, 2, student2);cout << student2.ID << student2.name << "\n";ListGetStu(demo, 1, student2);cout << student2.ID << student2.name << "\n";cout << ListGetIndex(demo, student) << "\n";ListMerge(demo, demo);ListaddAll(demo, demo);cout << demo.length;return 0;
}

在这里插入图片描述

链表

链表和顺序表其实是差不多的
顺序表在访问下一个的时候是用下标访问
链表访问下一个只能通过结构体中的指针

插入,删除的时候不需要改变其他元素,只需要修改指定元素前后元素的指针即可

//此链表的index为序列号从1开始    !!!!不是下标
//此链表多处用到new ,建议大家删一个new调试一下,就能了解到new和不用new的区别了#include "iostream"
#include "vector"using namespace std;typedef struct LNode {  //LNode类型 包含一个int值和一个指针指向下一个地址int data;struct LNode *next;
} LNode, *LinkList;bool ListInit(LinkList &L, int val) {   //初始化链表,要给一个初始值当作链表头节点L = new LNode;L->next = NULL;L->data = val;return true;
}bool ListInsertE(LinkList &L, int val) {    //添加一个元素到链表尾端LNode *headL = new LNode;   //保存一下链表当前的位置headL = L;while (L->next) {   //循环到L最后面,然后把当前值给L的下一个L = L->next;}LNode *temp = new LNode;    //new一个结点,如果不new可能会使用上一个temp结点temp->data = val;temp->next = NULL;L->next = temp;L = headL;  //链表的头位置给L
}bool ListInsert(LinkList &L, int index, int val) {  //插入到链表的序列index(注意不是下标)位置LNode *headL = new LNode;   //保存头位置的上一个(headL的下一个是头位置)headL->next = L;            //这里不保存头位置,    防止添加第一个位置时,链表会添加到第二个位置int j = 0;while (headL && j < (index - 1)) {      //找到第index个位置j++;headL = headL->next;}if (!headL || index < 1) {return false;}LNode *temp = new LNode;    //new一个结点,(不new可能会用到上一个结点)temp->data = val;temp->next = headL->next;   //把headL的下一个结点给temp的下一个结点headL->next = temp;         //把temp给headL的下一个结点     现在temp的下一个就是原headL的下一个结点,相当于把temp插入到了里面L = headL->next;return true;
}bool ListDelete(LinkList &L, int index) {   //删除指定序列index的值LNode *headL = new LNode;LNode *tempL = new LNode;tempL->next = L;            //tempL的下一个是头节点(防止删除第一个结点出现问题)headL = tempL;              //保存头结点的上一个,就是tempLint j = 0;while (tempL && j < (index - 1)) {  //找到序列index的结点tempL = tempL->next;j++;}if (!tempL) {   //如果tempL为NULL,直接退出,没有要删除的结点return false;}tempL->next = tempL->next->next;    //tempL的下一个的下一个给下一个   相当于下一个会被直接盖住(删除了下一个   )L = headL->next;    //把头结点给L
}bool ListGetElem(LinkList L, int index, int &val) {     //找到知道序列index的值,传送给valint j = 0;while (L && j < (index - 1)) {  //找到序列为index的值L = L->next;j++;}if (!L) {       //如果L为空,直接退出,没有此节点return false;}val = L->data;return true;
}int ListGetIndex(LinkList L, int val) {     //通过值找到指定序列下标int index = 1;while (L->data != val) {L = L->next;index++;}if (!L) {return 0;}return index;
}void ListCreateH(LinkList &L, vector<int> num) {    //前插法创建节点(num数组的值创建链表)L = new LNode;L->next = NULL;for (int i = 0; i < num.size(); i++) {LNode *p = new LNode;p->data = num[i];p->next = L->next;  //每次把L的下一个给p的下一个L->next = p;        //然后把p给L的下一个    p的下一个是原来L的下一个}L = L->next;    //L的下一个才是num数组创建的第一个值
}void ListCreateE(LinkList &L, vector<int> num) {    //前插法创建节点(num数组的值创建链表)L = new LNode;LNode *headL = new LNode;headL = L;L->next = NULL;for (int i = 0; i < num.size(); i++) {LNode *p = new LNode;p->data = num[i];p->next = NULL;L->next = p;    //当前指针p给L的下一个L = p;          //把p给L     p的上一个就是原L}L = headL->next;    //头结点的下一个才是num创建的第一个结点
}void ListPrint(LinkList L) {    //输出链表各个的值while (L) {cout << L->data << " ";L = L->next;}cout << "\n";
}
int main() {vector<int> num = {1,2,3,4,5};LinkList temp;
//    ListCreateE(temp, num);
//    ListPrint(temp);
//    ListCreateH(temp, num);
//    ListPrint(temp);ListInit(temp, 10);     //创建List链表ListInsertE(temp, 10);  //尾端插入值ListInsertE(temp, 10);ListPrint(temp);ListInsert(temp, 1, 20);    //插入一个值 到序列index位置ListPrint(temp);ListDelete(temp, 3);            //删除链表中序列index的值ListPrint(temp);int val;ListGetElem(temp, 3, val);      //通过序列index找到值,传给valcout << val << "\n";ListPrint(temp);cout << ListGetIndex(temp, 2) << "\n";  //通过值找到序列index}

在这里插入图片描述

双向循环链表

双向循环链表和单链表也是大致相同的
只是在修改结点的关系的时候需要修改每个结点的前后节点
//循环链表
#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;   //记录一下头结点,初始化结束后,把头结点重新赋值给LDuLNode *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;  //把初始头结点给Lreturn true;
}bool ListGetDulElem(DuLinkList L, int index, DuLNode &node) {   //得到链表序列为index的值,传给nodeint j = 1;while (L && j < index) {    //找到序列为index的结点,L = L->next;            //前面有几个,就循环几次,每次都向下走一位j++;}if (!L) {   //如果L为空,直接跳过return false;}node = *L;  //如果不为空,把当前结点传给nodereturn true;
}bool ListInsertDul(DuLinkList &L, int index, int data) {    //在序列index位置插入结点DuLNode *node = new DuLNode;if (!ListGetDulElem(L, index, *node)) { //查找一下指定index位置,如果没有当前位置,返回falsereturn false;}//假设在a b的位置插入c(在a b中间插入c,b为node,c为newNode)//设置c的前一个为a      设置a的下一个为c    设置c的下一个为b    设置b的上一个为cDuLNode *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的结点,传给nodereturn false;}//删除node(node为序列index的结点)//假设a b c删除 b   (b为node)//设置a的下一个为c     设置c的上一个为anode->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;
}

在这里插入图片描述

顺序表和链表的区别

顺序表链表
插入删除效率低插入删除效率高
存取元素效率高存取元素效率高
顺序表在空间中是一块连续的地址链表在空间中地址不连续

和顺序表有点类似
他只能返回栈顶元素,添加栈顶元素
#include "iostream"using namespace std;
#define MAXSIZE 100     //设置栈的大小
typedef struct {        //栈结构体:栈顶指针,栈底指针,栈的容量int *base;int *top;int stacksize;
}SqStack;bool InitStack(SqStack &S) {    //初始化栈S.base = new int[MAXSIZE];  //创建MAXSIZE大小的空间if (!S.base) {  //如果没创建成功返回falsereturn false;}S.top = S.base; //当前栈没有内容,栈顶和栈底指向一个位置S.stacksize = MAXSIZE;  //栈的容量为MAXSIZEreturn true;
}bool Push(SqStack &S, int data) {   //把data入栈if (S.top - S.base == S.stacksize) {    //如果栈顶-栈底==栈的容量,证明栈满了,无法添加数据return false;}*S.top++ = data;    //top指针位置添加元素,top指向后一个位置return true;
}bool Pop(SqStack &S, int &data) {   //出栈,返回值给dataif (S.top == S.base) {      //如果栈顶和栈底指向同一个位置,说明栈内没元素return false;}data = *--S.top;        //top指针前移,把值给datareturn true;
}bool Peek(SqStack &S, int &data) {  //peek返回值给data,但栈内不删除if (S.top != S.base) {data = *(S.top - 1);    //返回top指针前一个位置的值给datareturn true;}return false;
}bool StackPrint(SqStack S) {    //输出栈内元素,这里传的不是地址,如果传地址用完还要把指针改到栈顶while (S.top != S.base) {   //只要栈顶和栈底不是同一个位置,证明栈内元素没有空cout << *--S.top << " ";}cout << "\n";
}int main() {SqStack stack;InitStack(stack);   //初始化Push(stack,10);Push(stack,30);Push(stack,20);Push(stack,50);StackPrint(stack);int val;Pop(stack, val);    //出栈cout << val << " \n";StackPrint(stack);Peek(stack, val);   //返回栈顶的值,不删除cout << val << " \n";StackPrint(stack);return 0;
}

在这里插入图片描述

栈实现括号问题

给定一个字符串,里边可能包含( ) 这一种种括号,请编写程序检查该字符串的括号是否成对出现。

#include "iostream"
#include "stack"using namespace std;int main() {stack<char> s;  //栈存左括号,当前括号为左括号就压栈,如果遇到右括号就弹出一个左括号string str;cin >> str;     //输入字符串for (int i = 0; i < str.size(); i++) {if (str[i] == '(') {    //遇到左括号就压栈s.push('(');} else {    //遇到右括号就出栈,就是一个左括号配对一个右括号if (s.size() == 0) {    //如果此时没有左括号,在弹出说明左括号不足,无法匹配括号cout << "无法匹配————右括号多了";return 0;}s.pop();}}if (s.size() != 0) {    //如果循环完成后,栈内还有左括号,证明左括号多了,无法完成匹配cout << "无法匹配————左括号多了";} else {cout << "可以匹配";}return 0;
}

循环链栈表

栈的链表
栈和链栈的区别就是顺序表和单链表的区别
入栈和出栈只需要改变指定结点的关系
因为栈是单方向的,所以只需要改变单方向结点的关系
#include "iostream"using namespace std;typedef struct StackNode{   //链栈结构体:一个数据,一个指向下一位的指针int data;struct StackNode *next;
}StackNode, *LinkStack;bool InitStackNode(LinkStack &L) {  //初始化链栈,直接给链表NULL就可以L = NULL;return true;
}//此压栈方法和单链表的前插法有点类似(如果用后插法,无法访问到上一个结点)
bool Push(LinkStack &L, int data) { //压入data数据进入链栈StackNode *temp = new StackNode;temp->data = data;      //给temp数据temp->next = L;         //temp的下一个指向LL = temp;               //temp给L
}bool Pop(LinkStack &L, int &data) { //出栈(把数据传给data)if (L == NULL) {return false;}data = L->data;     //传给data,L指向下一个L = L->next;return true;
}bool Peek(LinkStack &L, int &data) {    //返回栈顶元素(给data)if (L != NULL) {data = L->data;return true;}return false;
}void linkStackPrint(LinkStack L) {  //输出链栈while (L) {cout << L->data << " ";L = L->next;}cout << "\n";
}int main() {LinkStack stack;InitStackNode(stack);   //初始化链栈,插入数据Push(stack,12);Push(stack,56);Push(stack,15);Push(stack,43);linkStackPrint(stack);int val;Pop(stack, val);    //栈顶结点出栈cout << val << "\n";linkStackPrint(stack);Peek(stack, val);   //返回栈顶元素(不删除栈顶元素)cout << val << "\n";linkStackPrint(stack);Push(stack,15); //入栈linkStackPrint(stack);
}

在这里插入图片描述

递归斐波那契

递归,其实就是自己不断的调用自己,每次改变参数

第五项的斐波那契 就是第四项+第三项
初始值,第一项,第二项的值为1
第三项的值就是前两个相加
第n项就是(n-1)+(n-2) 不断的调用自己
当找到第1项和第2项的时候直接返回1,我们默认第一项和第二项为1 上面的默认值,我们也称为递归的出口

**递归还有很多变种,(DFS,BFS)在后面的博客中会一一细说的**

#include "iostream"using namespace std;int f(int n) {if (n == 1 || n == 2) {return 1;}return f(n - 1) + f(n - 2);
}int main() {cout << f(5);
}

递归汉诺塔

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

/*根据汉诺塔的规则:一次只能移动一个托盘,而且必须保证小托盘在大托盘上面,完成A的托盘移动到C设 1号 为最小的托盘,用递归思路把这个问题分开,如果想把 n 号托盘移动,需要把 n 号上面的托盘都移动了然后我们转去移动 n-1 号托盘,一直找到最上面的托盘当移动 1 号托盘的时候,直接移动到C即可为什么移动n-1号托盘的时候是传入的Hanoi(n - 1, A, C, B)Hanoi(n, A, B, C) 是把 n 号托盘从A->C如果 1号 直接移动到C那么 2号 的时候就要先移动到B,中转一下,(1号 在C,把 1号 移动到B,空出C来给3号)3号 移动的时候移动到C,(然后再慢慢把B上的转到C上面(!!!并不是一步从B转到C),把B空出来给下一个托盘)……一直重复如此不难发现,1->C,2-B,3->C,4->B……这就是为什么每次都要C和B换位置的原因,n号移动到B,n-1号就要移动到C!!!所有的A B C都不是固定的ABC  都和这种类似,临时的ABC(这么做其实就是确保递归时每次都是从当时方法的目的是A->C 而不是一直要自己变动A->B,A->C  把参数改了,方法不变,就达到一直变动的目的了)当我们 n-1号 托盘移动完成后(同时意味着 1到(n-1) 都移动完成了),我们就可以把 n号 托盘从A直接转到C上n号移动以后,把1到(n-1)号托盘从B移动到C,重复上面的操作如果还是不好理解,多看一看动图理解,或者调试调试代码理解,只看不做很难理解Talk is Cheap, Show me the Code.
*/

**递归中所有的A B C都不是固定的ABC**

#include "iostream"using namespace std;int step = 1;
void Hanoi(int n, char A, char B, char C) { //将编号为n的托盘从A移动到C,B当作中间托盘if (n == 1) {cout << "步数:" << step++ << " 托盘:" << n << "  " << A << "->" << C << "\n";} else {Hanoi(n - 1, A, C, B);  //把(1-(n-1)号托盘)A->B C做中转结点cout << "步数:" << step++  << " 托盘:" << n << "  " << A << "->" << C << "\n";Hanoi(n - 1, B, A, C);  //把(1-(n-1)号托盘)B->C A做中转结点}
}
int main() {Hanoi(3,'A','B','C');return 0;
}

在这里插入图片描述

循环队列

循环队列,有点类似双指针数组
左指针存数据后,左指针左移,如果是左端的话,左移到右端
右指针存数据后,右指针右移,如果是右端的话,右移到左端
#include "iostream"using namespace std;#define MAXSIZE 10
typedef struct{ //队列结构体:数据,头指针,尾指针int *num;int front;int rear;
}SqQueue;bool InitQueue(SqQueue &S) {    //初始化队列S.num = new int[MAXSIZE];S.front = S.rear = 0;   //头指针和尾指针在一块(初始没有数据)return true;
}int QueueLength(SqQueue S) {    //返回长度(尾结点-头结点)return (S.rear - S.front + MAXSIZE) % MAXSIZE;//加上MAXSIZE防止出现负数,有可能出现头结点比尾结点大的情况
}bool QueueInsertHead(SqQueue &S, int data) {    //队列头结点插入if ((S.front - 1 + MAXSIZE) % MAXSIZE == S.rear) {  //判断一下是不是满了return false;}S.num[S.front] = data;  //插到头结点//因为他是队列,如果头指针在下标0的地方,那么前移就移动到末尾了S.front = (S.front - 1 + MAXSIZE) % MAXSIZE;    //头指针前移,防止指针-1小于0,return true;
}bool QueueInsertEn(SqQueue &S, int data) {  //队列尾结点插入if ((S.rear + 1) % MAXSIZE == S.front) {    //看是不是满的,尾结点+1可能超过末端,超过末端就从起始端开始算return false;}S.rear = (S.rear + 1) % MAXSIZE;    //后移一位S.num[S.rear] = data;   //存放数据return true;
}bool QueueDeleteHead(SqQueue &S, int &data) {   //删除头结点,传给dataif (S.front == S.rear) {    //如果是空的没办法传return false;}S.front = (S.front + 1) % MAXSIZE;  //头结点后移一位data = S.num[S.front];  //把值传给datareturn true;
}bool QueueDeleteEn(SqQueue &S, int &data) { //删除尾结点,传给dataif (S.front == S.rear) {    //判断是否为空return false;}data = S.num[S.rear];   //把值传给dataS.rear = (S.rear - 1 + MAXSIZE) % MAXSIZE;  //尾指针前移return true;
}bool QueueGetHead(SqQueue &S,int &data) {   //得到头结点if (S.front == S.rear) {return false;}data = S.num[(S.front + 1) % MAXSIZE];return true;
}bool QueueGetEnd(SqQueue &S, int &data) {   //得到尾结点if (S.front == S.rear) {return false;}data = S.num[S.rear];return true;
}bool QueuePrint(SqQueue S) {    //输出队列while (S.front != S.rear) {S.front = (S.front + 1) % MAXSIZE;cout << S.num[S.front] << " ";int temp = S.num[S.front];}cout << "\n";
}int main() {SqQueue queue;InitQueue(queue);QueueInsertHead(queue, 10);QueueInsertEn(queue, 40);QueueInsertHead(queue, 20);QueueInsertEn(queue, 30);QueuePrint(queue);int data;QueueDeleteEn(queue, data);cout << "删除尾结点:" << data << "\n";QueueDeleteHead(queue, data);cout << "删除头结点:" << data << "\n";QueueGetHead(queue, data);cout << "得到头结点:" << data << "\n";QueueGetEnd(queue, data);cout << "得到尾结点:" << data << "\n";cout << "得到长度:" << QueueLength(queue) << "\n";QueuePrint(queue);
}

在这里插入图片描述

链队(链式队列)

每个结点有一个指向下一位的指针
相对双向循环链表简单
#include "iostream"using namespace std;typedef struct QNode {  //结点结构体:值,下一位的指针int data;struct QNode *next;
} QNode, *QueuePtr;typedef struct {    //队列包含一个头指针,一个尾指针QueuePtr front;QueuePtr rear;
} LinkQueue;bool InitQueue(LinkQueue &Q) {  //初始化队列Q.front = Q.rear = new QNode;   //创建头尾结点Q.front->next = NULL;           //头结点的下一个为空Q.front->data = Q.rear->data = NULL;    //初始时,头尾结点值为NULLreturn true;
}bool LinkQueueInsertEnd(LinkQueue &Q, int data) {   //添加元素到队尾if (Q.front == Q.rear && Q.front->data == NULL) {   //如果是第一次进来Q.rear->data = data;    //赋初值return true;}Q.rear->next= new QNode;Q.rear->next->data = data;  //给尾结点的下一个赋值Q.rear = Q.rear->next;      //尾结点指向尾结点的下一个Q.rear->next = NULL;        //尾结点的下一个为空return true;
}bool LinkQueueDeleteHead(LinkQueue &Q, int &data) { //删除头结点if (Q.front == Q.rear) {return false;}QNode *temp = new QNode;data = Q.front->data;   //保存头结点的值Q.front = Q.front->next;    //头指针指向下一位
}bool LinkQueueGetHead(LinkQueue &Q, int &data) {    //得到头结点if (Q.front != Q.rear) {    //队列不为空就返回data = Q.front->data;return true;}return false;
}void LinkQueuePrint(LinkQueue Q) {  //输出队列的值while (Q.front != Q.rear->next) {cout << Q.front->data << " ";Q.front = Q.front->next;}cout << "\n";
}int main() {LinkQueue linkQueue;InitQueue(linkQueue);LinkQueueInsertEnd(linkQueue, 10);LinkQueueInsertEnd(linkQueue, 20);LinkQueueInsertEnd(linkQueue, 30);LinkQueueInsertEnd(linkQueue, 40);LinkQueuePrint(linkQueue);int val;LinkQueueDeleteHead(linkQueue, val);cout << "删除的头结点值为:" << val << "\n";LinkQueueGetHead(linkQueue, val);cout << "得到的头结点值为:" << val << "\n";return 0;
}

在这里插入图片描述


http://chatgpt.dhexx.cn/article/RA4HLwBu.shtml

相关文章

考研_数据结构

绪论 1.算法原地工作是指辅助空间不随着数据规模的增大而增大&#xff0c;不是说不需要辅助空间 2.栈和队列属于逻辑结构而非存储结构&#xff0c;它们的实现才属于存储结构 3.数据元素是数据的基本单位&#xff0c;数据项是数据的最小单位 4.程序需要算法和数据结构结合在…

2019数据结构考研(一)

2019数据结构考研(一) 知识框架 数据结构的基本概念 数据:数据是信息的载体,是所有能描述事物属性的数,字符以及所有能输入到计算机被计算机程序识别和处理的符号的集合数据元素:数据元素是数据的基本单位数据项:数据项是构成数据元素不可分割的最小单位注意:不要混淆数据,数…

考研数据结构汇总

仅供参考&#xff01;&#xff01;&#xff01; 必背知识点 数据结构 是相互之间存在一种或多种特定关系的数据元素的集合 数据结构的三要素&#xff1a; 逻辑结构&#xff0c;存储结构&#xff0c;数据的运算&#xff08;定义&#xff08;逻辑结构的&#xff0c;运算的功能…

22计算机408考研—数据结构—排序(详解加例题)

2022计算机考研408—数据结构—排序 手把手教学考研大纲范围内的排序 22考研大纲数据结构要求的是C/C&#xff0c;笔者以前使用的都是Java&#xff0c;对于C还很欠缺&#xff0c; 如有什么建议或者不足欢迎大佬评论区或者私信指出 Talk is cheap. Show me the code. 理论到处都…

王道考研数据结构笔记

2022年4月16日 整理了这篇博客的pdf版本&#xff0c;但是缺的部分可能没法补上啦&#xff0c;把毕业的事忙完了可能&#xff01;可以&#xff01;对着书把笔记再整理一遍&#xff01;所以所以&#xff0c;如果有需要pdf版本的可以私信我(可能回得比较慢&#xff0c;也可以直接加…

数据结构(考研笔记)

参考 原文链https://blog.csdn.net/qq_55593227/article/details/123598044 文章目录 第一章、绪论1.1. 数据结构1.2. 算法1.2.1. 算法的基本概念1.2.2. 算法的时间复杂度1.2.3. 算法的[空间复杂度](https://so.csdn.net/so/search?q空间复杂度&spm1001.2101.3001.7020) 第…

【数据结构】- 【考研复试面试题】-汇总大合集

数据结构-考研复试面试题-汇总大合集 _写在前面的话&#xff1a;第二次写文章&#xff0c;本篇文章涉及内容主要包括数据结构与算法&#xff0c;包含市面上最热门的面试题&#xff0c;加以总结&#xff0c;用于本人的专业课面试复习&#xff0c;包括一些个人理解和总结&#xf…

考研复试——数据结构

文章目录 数据结构什么是数据结构&#xff1f;逻辑结构和物理结构有什么区别&#xff1f;为什么对单链表设置头结点&#xff1f;算法的特点&#xff1f;常见的数据结构有哪些&#xff1f;栈在后缀表达式求值的算法思想&#xff1a;队列溢出现象&#xff1f;解决方法&#xff1f…

【考研】数据结构知识点

绪论 基本概念和术语 数据 :信息的载体数据元素 &#xff1a;数据的基本单位&#xff0c;由若干数据项组成&#xff0c;数据项为不可分割的最小单位数据对象 &#xff1a;数据的子集&#xff0c;具有相同性质的数据元素集合数据类型 &#xff1a;值的集合和定义在此集合的一组…

考研数据结构-基础知识

考验数据结构所需的程序语言基础&#xff1a; 一、&#xff08;1&#xff09;基本类型&#xff1a; 数据类型&#xff1a;short、int、long、float、double&#xff08;用来存储各种数字如整数、小数&#xff09;。考验数据结构中常用的有两种&#xff1a;int&#xff08;存储整…

数据结构考研复习(详细指导)(持续更新中)

目录 绪论 数据结构 数据结构在学什么 ​编辑 数据结构的基本概念 算法 算法的基本概念 算法的特性 好算法的特性 算法的时间复杂度 算法的空间复杂度 线性表 定义 基本操作 顺序表 顺序表的定义 顺序表的实现 顺序表的插入和删除 顺序表的查找 单链表 单链…

《王道》数据结构笔记整理2022

数据结构 第一章&#xff1a;绪论1.1数据结构的基本概念1.2数据结构的三要素1.3算法的基本概念1.4算法的时间复杂度1.5算法的空间复杂度 第二章&#xff1a;线性表2.1线性表的定义2.2顺序表的定义2.2.1静态分配:2.2.2动态分配 2.2顺序表的基本操作1.插入操作 &#xff1a;平均时…

跨境支付体系

跨境支付基础概念 两个或两个以上国家或地区之间因国际贸易&#xff0c;国际投资及其他方面所发生的国际间债权债务&#xff0c;借助一定的结算工具和支付体系实现资金跨国或跨地区转移的行为。 主要特性&#xff1a; 1&#xff09;收付双方可能在不同的国家或地区 2&#xff0…

Braintree-国外支付对接(一)

前言&#xff1a;在国外&#xff0c;要说网上商城支付用的最多的就是Paypal和信用卡。Paypal相当于咱中国的支付宝&#xff0c;所以支付要对接它是必不可少的。在开发项目的初期最先对接的确是Paypal的Rest SDK&#xff0c;后来鉴于领导的要求&#xff0c;需要适用信用卡&#…

支付开发,不得不了解的国内、国际第三方支付流程

https://mp.weixin.qq.com/s/4Xut45PcMASlV4_08O_xmA 这几年的工作中一直与支付打交到&#xff0c;借着 skr-shop 这个项目来与大家一起分享探索一下支付系统该怎么设计、怎么做。我们先从支付的一些常见流程出发分析&#xff0c;找出这些支付的共性&#xff0c;抽象后再去探讨…

澳洲支付服务商RoyalPay微信支付宝APP支付对接

最近项目中需要开发澳洲那边的微信支付宝支付&#xff0c;所以去研究了一下微信境外支付&#xff0c;发现境外只支持服务商模式&#xff0c;即客户需要去与澳洲本地服务商合作&#xff0c;由客户提供材料&#xff0c;服务商帮客户申请支付相关账号&#xff0c;然后调用服务商提…

聚合支付平台排名

随着时代的发展&#xff0c;聚合支付对于商家来说越来越重要&#xff0c;虽说有刷脸支付的噱头&#xff0c;但是聚合支付在支付史上的地位越来越重要。再加上银联、支付宝、微信官方这两年在聚合支付上的发力&#xff0c;和国家层面对聚合支付的政策扶持&#xff0c;聚合支付已…

聚合支付排名前十的平台有哪些?

很多行业都有自己的排名&#xff0c;在某种程度上&#xff0c;排名的位置&#xff0c;决定着企业能力的强弱&#xff0c;越是排名靠前的企业&#xff0c;越是彰显着不菲的能力。 所以&#xff0c;很多时候&#xff0c;我们想寻找某个行业里优秀的企业&#xff0c;看一下排名数…

第三方支付平台排行!

第三方支付平台排行&#xff01; 2023年第三方支付十大品牌 口碑投票榜 人气品牌榜 2023年榜单规则依据:第三方支付十大品牌榜数据由CNPP品牌榜中榜大数据 研究院和CN10排排榜技术|研究院通过资料收集整理&#xff0c;并基于大数据统计及人为根据市场和参数条件变化的分析研究…

海外本地支付—Payssion

Payssion&#xff08;全球本地支付&#xff09;&#xff1a;成立于2013年1月15日&#xff0c;致力于为客户提供一站式全球在线支付解决方案。通过Payssion一个API可以快速接入全球300多种本地支付&#xff0c;覆盖欧洲、拉美、中东、东南亚等全球200多个国家/地区。 1、提供什么…