线性表
顺序表
SeqList.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#define INITSIZE 16
#define MAXSIZE 128
typedef int ElemType;
/*
一维数组静态分配
*/
typedef struct {
ElemType data[MAXSIZE]; //静态表的主体用来保存数据
int length; //用来记录当前顺序表的长度
}SqlList; //给顺序表起一个别名SqlList
/*
一维数组的动态分配
*/
typedef struct {
ElemType* data;
int length; //用来记录当前长度
int capacity; //记录当前容量
}DySqlList;
void initList(SqlList& L);
void creatList(SqlList& L);
//销毁顺序表
void destroyList(SqlList& L);
//插入操作。在表L中第pos个位置上插入指定元素e
bool insertList(SqlList& L, int pos, ElemType e);
//删除操作,删除表L中第pos个位置(下标为pos-1)的元素,并用e返回删除元素的值
bool deleteList(SqlList& L, int pos, ElemType& e);
//按值查找操作。在表L中查找具有给定关键字值的元素,若存在返回第一个值为e的所在位置,不存在返回0
int locateElem(SqlList L, ElemType e);
//按位查找操作。获取表L第pos个位置的元素的值
ElemType getElem(SqlList L, int pos);
//判空操作。若L为空表,则返回true,否则返回false
bool isEmpty(SqlList L);
//顺序输出顺序表
void printList(SqlList L);
SqList.cpp
#include"SqlList.h"
#include<stdio.h>
//初始换顺序表,构造一个空的顺序表
void initList(SqlList& L) {
//防止出现脏数据,所以先遍历将所有值赋为0
for (int i = 0; i < MAXSIZE; i++) {
L.data[i] = 0;
}
// 表长初始化为-1
L.length = -1;
}
// 创建顺序表
void creatList(SqlList& L) {
ElemType x;
int i = 0;
printf("请输入数据:");
scanf("%d", &x);
while (x != 999) //当输入999代表输入结束
{
L.data[i++] = x;
scanf("%d", &x);
}
L.length = i; //设置表长
}
//销毁顺序表
void destroyList(SqlList& L) {
for (int i = 0; i < L.length; i++) {
L.data[i] = 0;
}
L.length = 0;
}
//插入操作。在表L中第pos个位置上插入指定元素e
bool insertList(SqlList& L, int pos, ElemType e) {
if (L.length > MAXSIZE) {
printf("表已满!不允许再插入!!!");
return false;
}
if (pos < 1 || pos > L.length + 1) {
printf("pos位置不合法!!!");
return false;
}
for (int i = L.length - 1; i >= pos - 1; i--) {
L.data[i + 1] = L.data[i];
}
L.data[pos - 1] = e; //插入数据
L.length++; // 表长+1
return true;
}
//删除操作,删除表L中第pos个位置(下标为pos-1)的元素,并用e返回删除元素的值
bool deleteList(SqlList& L, int pos, ElemType& e) {
if (L.length < 0) {
printf("表为空!不允许删除!!!");
return false;
}
if (pos < 1 || pos > L.length) {
printf("pos位置不合法!!!");
return false;
}
e = L.data[pos - 1];
for (int i = pos; i <= L.length - 1; i++) {
L.data[i - 1] = L.data[i];
}
L.length--;
return true;
}
//按值查找操作。在表L中查找具有给定关键字值的元素,若存在返回第一个值为e的所在位置,不存在返回0
int locateElem(SqlList L, ElemType e) {
for (int i = 0; i < L.length; i++) {
if (L.data[i] == e) {
return i + 1;
}
}
return 0;
}
//按位查找操作。获取表L第pos个位置的元素的值
ElemType getElem(SqlList L, int pos) {
if (pos < 1 || pos > L.length) {
return -999;
}
return L.data[pos - 1]; //下标是从0开始,位置是从1开始的
}
//判空操作。若L为空表,则返回true,否则返回false
bool isEmpty(SqlList L) {
/*if (L.length == 0) {
return true;
}
else {
return false;
}*/
return L.length == 0;
}
//顺序输出顺序表
void printList(SqlList L) {
if (isEmpty(L)) {
return;
}
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
printf("\n");
}
测试代码main.cpp
#include"SqlList.h"
#include<stdio.h>
int main() {
SqlList L;
initList(L);
creatList(L);
printList(L);
//------测试插入-------------
insertList(L, 2, 1000);
printList(L);
//-------测试删除------------
ElemType e;
deleteList(L, 1, e);
printf("你删除的元素e为:%d\n", e);
printList(L);
//-------测试添加------------
insertList(L, 2, 66);
printList(L);
//-------测试查找特定位置值-----------
int pos = locateElem(L, 100);
printf("值为100的位置为:%d", pos);
//-------测试销毁-------
destroyList(L);
printList(L);
return 0;
}
默认输入999代表输入结束,这里我就没贴全部的测试图片了,大家可以自行测试
单链表(带头节点和不带头节点)
LinkList.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
typedef int ElemType;
// 定义单链表结构体
typedef struct LNode{
ElemType data; // 数据域
LNode* next; //用来保存后继节点的指针
}LNode,*LinkedList;
// 另一种实现方式
/*
typedef struct LNode {
ElemType data; // 数据域
LNode* next; //用来保存后继节点的指针
}LNode;
typedef struct{
LNode* head;
int length; //用来记录表长
}LinkedList;
*/
//初始化单链表
void initLinkList(LinkedList& L);
//头插法创建单链表(不带头结点)
void createListByHead(LinkedList& L);
//尾插法创建单链表(不带头结点)
void createListByTail(LinkedList& L);
// 返回第pos个位置上的结点(不带头结点)
LNode* getNode(LinkedList L, int pos);
//按值查找结点(不带头结点)
LNode* locateElem(LinkedList L, ElemType e);
// 在第pos个位置插入元素e(不带头结点)
void insertElem(LinkedList& L, int pos, ElemType e);
// 删除第pos个位置的元素结点,并用e返回被删除结点的元素值(不带头结点)
void deleteElem(LinkedList& L, int pos, ElemType& e);
// 求单链表的长度
int getLength(LinkedList L);
// 打印链表
void printLinkList(LinkedList& L);
///
//初始化单链表(带头结点)
void initLinkListWithHead(LinkedList& L);
//头插法创建单链表(带头结点)
void createListWithHead(LinkedList& L);
//尾插法创建单链表(带头结点)
void createListByTailWithHead(LinkedList& L);
// 返回第pos个位置上的结点(不带头结点)
LNode* getNodeWithHead(LinkedList L, int pos);
//在第pos个位置插入元素e(带头结点)
void insertElemWithHead(LinkedList& L, int pos, ElemType e);
// 删除第pos个位置的元素结点,并用e返回被删除结点的元素值(带头结点)
void deleteElemWithHead(LinkedList& L, int pos, ElemType& e);
LinkList.cpp
#include "LinkList.h"
#include<stdio.h>
#include<cstdlib>
//初始化单链表(带头结点)
void initLinkListWithHead(LinkedList& L) {
L = (LNode*)malloc(sizeof(LNode)); //创建一个头结点
if (L) { //申请头结点成功
L->next = NULL;
}
}
//头插法创建单链表(带头结点)
void createListWithHead(LinkedList& L) {
ElemType x;
scanf_s("%d", &x);
while (x != 999)
{
LNode* s = (LNode*)malloc(sizeof(LNode));
s->data = x;
s->next = L->next;
L->next = s;
scanf_s("%d", &x);
}
}
//尾插法创建单链表(带头结点)
void createListByTailWithHead(LinkedList& L) {
LNode* tail = L; //添加一个尾指针
ElemType x;
scanf_s("%d", &x);
while (x != 999) {
LNode* s = (LNode*)malloc(sizeof(LNode));
if (s == NULL) return;
s->data = x;
s->next = NULL;
tail->next = s;
tail = s;
scanf_s("%d", &x);
}
}
//返回第pos个位置上的结点
LNode* getNodeWithHead(LinkedList L, int pos) {
//检查pos是否合法,data是链表的长度
if (pos<0 || pos>L->data) {
return NULL;
}
int i = 0; //头节点在第一个位置所以i要从0开始
LNode* p = L;
while (p && i < pos) {
p = p->next;
i++;
}
return p;
}
//在第pos个位置插入元素e(带头结点)
void insertElemWithHead(LinkedList& L, int pos, ElemType e) {
//检查pos的合法性
if (pos < 1 || pos > getLength(L) + 1) {
printf("hhhhhh");
return;
}
LNode* cur = (LNode*)malloc(sizeof(LNode));//创建一个新节点
if (cur == NULL) return;
cur->data = e;
//找到要插入位置的前驱节点
LNode* pre = getNodeWithHead(L, pos - 1);
cur->next = pre->next;
pre->next = cur;
}
// 删除第pos个位置的元素结点,并用e返回被删除结点的元素值(带头结点)
void deleteElemWithHead(LinkedList& L, int pos, ElemType& e) {
//检查pos是否合法
if (pos<1 || pos>L->data) {
return;
}
LNode* removed = getNode(L, pos); //记录要删除元素
LNode* pre = getNode(L, pos - 1); //记录要删除元素的前一个元素结点
e = removed->data; //被删除元素用e接收返回
pre->next = removed->next; //被删除的前一个结点指向其后一个结点
free(removed); //释放删除结点的空间
}
///
///
//初始化单链表(不带头结点)
void initLinkList(LinkedList& L) {
L = NULL;
}
//头插法创建单链表(不带头结点)
void createListByHead(LinkedList& L) {
ElemType x;
scanf_s("%d", &x);
while (x != 999)
{
LNode* node = (LNode*)malloc(sizeof(LNode));
node->data = x;
node->next = NULL;
if (L == NULL) { //L为空说明是创建的是第一个节点
L = node;
}
else {
node->next = L;
L = node;
}
scanf_s("%d", &x);
}
}
//尾插法创建单链表(不带头结点)
void createListByTail(LinkedList& L) {
LNode* tail = NULL; //定义尾指针
ElemType x;
scanf_s("%d", &x);
while (x != 999) {
LNode* node = (LNode*)malloc(sizeof(LNode));
node->data = x;
node->next = NULL;
if (L == NULL) { //L为空说明是创建的是第一个节点
L = node;
tail = node;
}
else
{
tail->next = node; //尾指针指向新的节点
tail = node; // 尾指针后移
}
scanf_s("%d", &x);
}
}
// 返回第pos个位置上的结点(不带头结点)
LNode* getNode(LinkedList L, int pos) {
if (pos < 1) {
return NULL;
}
LNode* p = L;
int i = 1;
while (p != NULL && i < pos)
{
p = p->next;
i++;
}
return p;
}
//按值查找结点(不带头结点)
LNode* locateElem(LinkedList L, ElemType e) {
LNode* p = L;
while (p && p->data != e)
{
p = p->next;
}
return p;
}
//在第pos个位置插入元素e(不带头结点)
void insertElem(LinkedList& L, int pos, ElemType e) {
//检查pos的合法性
if (pos < 1 || pos > getLength(L) + 1) {
return;
}
LNode* node = (LNode*)malloc(sizeof(LNode));//创建一个新节点
node->data = e;
//如果是第一个位置的话
if (pos == 1) {
node->next = L;
L = node;
}
else
{
//找到要插入位置的前驱节点
LNode* pre = getNode(L, pos - 1);
node->next= pre->next;
pre->next = node;
}
}
// 删除第pos个位置的元素结点,并用e返回被删除结点的元素值(不带头结点)
void deleteElem(LinkedList& L, int pos, ElemType& e) {
//检查pos的合法性
if (pos < 1 || pos > getLength(L) + 1) {
return;
}
// 查找到第pos个元素
LNode* removed = getNode(L, pos);
if (pos == 1) {
L = removed->next; //如果是第一个位置直接将头指针后移
}
else
{
LNode* pre = getNode(L, pos - 1); //找到被删除元素结点的前驱节点
pre->next = removed->next;
}
e = removed->data; //将要删除的值保存到e中
free(removed); //释放被删除元素的空间内存
}
// 求单链表的长度
int getLength(LinkedList L) {
LNode* p = L;
int size = 0;
while (p)
{
p = p->next;
size++;
}
return size;
}
// 打印链表
void printLinkList(LinkedList& L) {
LNode* p = L->next;
while (p != NULL)
{
printf("%d->", p->data);
p = p->next;
}
printf("\n");
}
测试main.cpp
#include<stdio.h>
#include "LinkList.h"
int main() {
LNode* L;
//initLinkList(L);
//createListByHead(L);
//createListByTail(L);
//-------------------------
//LNode* p = getNode(L, 2);
//printf("第二个位置的值为:%d \n", p->data);
//-------------------------
//LNode* p = locateElem(L, 3);
//--------------------------
/*int size = getLength(L);
printf("链表的长度为:%d", size);*/
//--------------------------
//insertElem(L, 2, 88);
//--------------------------
//int e;
//deleteElem(L, 2, e);
//printf("删除的节点的值为:%d\n", e);
//printLinkList(L);
//
initLinkListWithHead(L);
//createListWithHead(L);
createListByTailWithHead(L);
insertElemWithHead(L, 2, 88);
printLinkList(L);
return 0;
}
默认输入999代表输入结束,这里我就没贴全部的测试图片了,大家可以自行测试
循环单链表
LinkedList.h
#pragma once
typedef int ElemType;
//定义链表节点结构体
typedef struct LNode {
ElemType data; // 定义数据域
LNode* next; // 定义指针域
}LNode;
// 定义循环单链表结构体
typedef struct LinkList {
LNode* head; // 头节点
LNode* tail; // 尾节点
}LinkedList;
// 初始化单链表
void initLinkedList(LinkedList& L);
// 头叉法创建单链表(带头节点)
void createLinkedListByHead(LinkedList& L, ElemType x);
// 尾插法创建单链表
void createLinkedListWithTail(LinkedList& L, ElemType x);
//返回第pos个位置上的结点
LNode* getNode(LinkedList L, int pos);
//在第pos位置插入元素e
void InsertLinkedList(LinkedList& L, int pos, ElemType data);
//打印链表
void printLinkedList(LinkedList L);
LinkedList.cpp 这里只考虑了带头节点都情况
#include<cstdio>
#include<cstdlib>
#include"LinkedList.h"
// 初始化单链表
void initLinkedList(LinkedList& L) {
L.head = (LNode*)malloc(sizeof(LNode)); //创建一个头结点
if (L.head == NULL) return;
L.head->next = NULL;
L.tail = L.head;
}
// 头叉法创建单链表(带头节点)
void createLinkedListByHead(LinkedList& L, ElemType x) {
LNode* node = (LNode*)malloc(sizeof(LNode));
node->data = x;
node->next = L.head->next; // 让新节点的next指向头结点的next
L.head->next = node; // 让头节点的next指向新节点
if (L.head == L.tail) { // 如果链表为空,也就是说插入的是第一条数据需要修改尾指针
L.tail = node;
}
}
// 尾插法创建单链表
void createLinkedListWithTail(LinkedList& L, ElemType x) {
LNode* node = (LNode*)malloc(sizeof(LNode));
node->data = x;
node->next = L.head; // 先新节点指向头结点,形成循环
L.tail->next = node; // 尾结点的next指向新节点
L.tail = node; // 尾结点后移
}
//返回第pos个位置上的结点
LNode* getNode(LinkedList L, int pos) {
// 如果位置不合法
if (pos < 0 || L.head == NULL) {
return NULL;
}
// 如果找到是第一个位置
if (pos == 1) {
return L.head;
}
int i = 0;
LNode* p = L.head->next; // 从头节点的next位置开始找
while (p != L.head && i < pos - 1)
{
p = p->next;
i++;
}
return p == L.head ? NULL : p; //如果再一次来到头指针即第一个元素位置证明没找到返回NULL,否则返回找到的p
}
//打印链表
void printLinkedList(LinkedList L) {
LNode* p = L.head->next;
while (p != L.head)
{
printf("%d->", p->data);
p = p->next;
}
printf("NULL\n");
}
// 在指定位置插入元素
void InsertLinkedList(LinkedList& L, int pos, ElemType data) {
if (pos < 1 || L.head == NULL) {
printf("位置不合法!\n");
return;
}
LNode* newNode = (LNode*)malloc(sizeof(LNode));
if (newNode == NULL) return;
newNode->data = data;
newNode->next = NULL;
if (pos == 1) { // 如果是第一个位置在链表头插入节点
newNode->next = L.head;
L.head = newNode;
if (L.head = L.tail) {
L.tail = newNode; // 更新尾节点的指针
}
}else {
LNode* p = L.head;
for (int i = 1; i < pos; ++i) { // 找到第pos-1个位置
p = p->next;
}
newNode->next = p->next;
p->next = newNode;
if (p == L.tail) { // 如果是在尾节点插入,需要修改尾指针的位置
L.tail = newNode;
}
}
}
main.cpp
#include<cstdio>
#include<cstdlib>
#include"LinkedList.h"
int main() {
LinkedList L;
initLinkedList(L);
int n,m,data;
printf("请输入你要创建的节点个数:");
scanf_s("%d",&n); // 8
//===================测试头插法========================================
//for (int i = 1; i <= n; i++) {
// createLinkedListByHead(L, i);
//}
//printf("当前链表中的元素为:");
//printLinkedList(L); // 8->7->6->5->4->3->2->1->NULL
//===================测试尾插法=========================================
for (int i = 1; i <= n; i++) {
createLinkedListWithTail(L, i); // 1->2->3->4->5->6->7->8->NULL
}
//printf("当前链表中的元素为:");
//printLinkedList(L); // 1->2->3->4->5->6->7->8->NULL
//====================测试获取指定位置节点================================
//printf("请输入你要获取的节点的位置:");
//scanf_s("%d", &m); // 2
//LNode* p = getNode(L, m);
//printf("第二个位置的元素为:%d ", p->data); // 2
//====================测试在指定位置插入指定节点===========================
printf("请输入你要插入的位置和值:"); // 2 666
scanf_s("%d %d", &m,&data);
InsertLinkedList(L, m, data);
printLinkedList(L); // 1->666->2->3->4->5->6->7->8->NULL
return 0;
}
测试截图
双链表
DNode.h
typedef int ElemType;
/*
创建双循环链表结构体
*/
typedef struct DNode {
ElemType data; // 数据域
DNode* prior; // 前驱指针
DNode* next; // 后继指针
}DNode,*DLinkedList;
// 双链表的初始化(带头结点)
void initDLinkedList(DLinkedList& L);
//头插法创建单链表
void createDListWithHead(DLinkedList& L);
//尾插法创建单链表
void createDListWithTail(DLinkedList& L);
//返回第pos个位置上的结点
DNode* getNode(DLinkedList L, int pos);
//在第pos个位置插入元素e
void insertElem(DLinkedList& L, int pos, ElemType e);
//删除第pos个位置上的元素。并用e接收被删除元素值
void deleteElem(DLinkedList& L, int pos, ElemType& e);
//打印双链表
void printDList(DLinkedList L);
DLinkedList.cpp
#include<cstdio>
#include<cstdlib>
#include"DNode.h"
// 初始化双链表(带头结点)
void initDLinkedList(DLinkedList& L) {
L = (DNode*)malloc(sizeof(DNode));
if (L) {
L->next = NULL;
L->prior = NULL;
L->data = 0; //使用头结点的数据域保存表长
}
}
//头插法创建单链表
void createDListWithHead(DLinkedList& head) {
ElemType x;
scanf_s("%d", &x);
while (x != 999)
{
DNode* node = (DNode*)malloc(sizeof(DNode));
if (node == NULL) return; //申请失败直接退出
node->data = x;
如果链表为空(插入第一个元素)
//node->next = L->next; // 为空的话L->next == NULL
//node->prior = L;
//L->next = node;
如果链表不为空
//node->next = L->next;
//L->next->prior = node;
//node->prior = L;
//L->next = node;
//合并一下就是
//=======插入操作========
node->next = head->next;
if (head->next != NULL) {
head->next->prior = node;
}
node->prior = head;
head->next = node;
//======================
head->data++; //长度加一
scanf_s("%d", &x);
}
}
//尾插法创建单链表
void createDListWithTail(DLinkedList& head) {
ElemType x;
scanf_s("%d", &x);
DNode* tail = head;
while (x != 999) {
DNode* node = (DNode*)malloc(sizeof(DNode));
if (node) {
node->data = x;
node->next = NULL;
//=======插入操作========
tail->next = node;
node->prior = tail;
tail = node;
//======================
head->data++;
}
scanf_s("%d", &x);
}
}
//返回第pos个位置上的结点
DNode* getNode(DLinkedList L, int pos) {
//检查pos是否合法,data是链表的长度
if (pos<0 || pos>L->data) {
return NULL;
}
int i = 0; //第0个位置代表了头结点的位置
DNode* p = L;
while (p && i < pos) { // 当p->next不为空,且i<pos
p = p->next;
i++;
}
return p;
}
//打印双链表
void printDList(DLinkedList L) {
DNode* p = L->next;
if (p == NULL) {
return;
}
while (p)
{
printf("%d->", p->data);
p = p->next;
}
//printDList(p); // 递归打印
printf("NULL\n");
}
//在第pos个位置插入元素e
void insertElem(DLinkedList& L, int pos, ElemType e) {
if (pos < 0 || pos > L->data + 1) { //pos位置不合法
return;
}
DNode* node = (DNode*)malloc(sizeof(DNode));
if (node) {
node->data = e;
node->next = NULL;
DNode* pre = getNode(L, pos - 1); // 找打第pos-1个位置
//=======================
node->next = pre->next;
if (pos != L->data + 1) { // 如果pos等于表长+1说明在最后一个位置插入
pre->next->prior = node;
}
node->prior = pre;
pre->next = node;
//======================
L->data++; //插入成功之后,表长+1
}
}
//删除第pos个位置上的元素。并用e接收被删除元素值
void deleteElem(DLinkedList& L, int pos, ElemType& e) {
if (pos<1 || pos>L->data) {
return;
}
DNode* pre = getNode(L, pos - 1);
DNode* removed = getNode(L, pos);
if (pos == L->data) {
pre->next = NULL;
}
else {
pre->next = removed->next;
removed->next->prior = pre;
}
e = removed->data;
free(removed);
L->data--;
}
main.cpp
#include<cstdio>
#include<cstdlib>
#include"DNode.h"
int main() {
DLinkedList L;
initDLinkedList(L);
//=====测试头插法创建链表=====
createDListWithHead(L);
//printDList(L);// 输入:1 2 3 4 5 6 7 8 999 结果:8->7->6->5->4->3->2->1->NULL
//=====测试尾插法创建链表=====
//createDListWithTail(L);
//printDList(L); // 输入:1 2 3 4 5 6 7 8 999 结果:1->2->3->4->5->6->7->8->NULL
//====测试获取第pos个位置的元素
//DNode* p = getNode(L, 3);
//printf("第3个位置的值为:%d \n", p->data);// 输入:1 2 3 999 结果:3
//printDList(L);
//====测试在第pos个位置插入元素=====
//insertElem(L, 4, 666);
//printDList(L); // 输入:1 2 3 999 结果:1->2->3->666->NULL
//====测试删除第pos个位置的值,并用元素e接收=====
ElemType e;
printf("删除前:");
printDList(L);// 删除前:8->7->6->5->4->3->2->1->NULL
deleteElem(L, 3, e);
printf("删除第3个位置的元素值为:%d \n", e); // 6
printf("删除后:");
printDList(L); // 删除后:8->7->5->4->3->2->1->NULL
return 0;
}
测试截图
栈
顺序栈
SqStack.h
#define _CRT_SECURE_NO_WARNINGS
#define MAXSIZE 50
typedef int ElementType;
/*
顺序存储栈数据结构
*/
typedef struct {
ElementType data[MAXSIZE]; // 定义栈的数据域用数组存储大小为MAXSIZE
int top; // 栈顶指针
}SqStack;
// 初始化栈
void InitStack(SqStack& S);
// 判断栈是否为空
bool StackIsEmpty(SqStack S);
// 进栈
bool Push(SqStack& S, ElementType x);
// 出栈
bool Pop(SqStack& S, ElementType& x);
// 读取栈顶元素
bool Peek(SqStack S,ElementType &x);
// 打印输出栈
void PrintStack(SqStack S);
SqStack.cpp
这里我考虑了top = -1 和 top == 0的情况
#include "SqStack.h"
#include<stdio.h>
// 初始化栈
void InitStack(SqStack& S) {
S.top = -1;
//S.top = 0;
}
// 判断栈是否为空
bool StackIsEmpty(SqStack S) {
return S.top == -1; //三元表达式
}
// 进栈
bool Push(SqStack& S, ElementType x) {
if (S.top > MAXSIZE - 1) // 栈满,直接返回false
return false;
S.data[++S.top] = x; //先让栈顶指针后移一位
//S.data[S.top++] = x; // 栈顶指针初始化为0的情况
return true;
}
// 出栈
bool Pop(SqStack& S, ElementType& x) {
if (StackIsEmpty(S)) //栈空。直接返回false
return false;
x = S.data[S.top--]; // 先将元素保存,栈顶指针再后移
//x = S.data[--S.top]; // 栈顶指针初始化为0的情况
return true;
}
// 读取栈顶元素
bool Peek(SqStack S, ElementType &x) {
if (StackIsEmpty(S)) //如果栈不为空,返回栈顶元素
return false;
x = S.data[S.top];
//x = S.data[S.top - 1];栈顶指针初始化为0的情况
return true;
}
// 打印输出栈
void PrintStack(SqStack S) {
while (S.top > -1) {
printf("%d ", S.data[S.top--]);
}
///
/*while (S.top > 0) {
printf("%d ", S.data[--S.top]);
}*/
printf("\n");
}
测试代码main.cpp
#include<stdio.h>
#include"Stack.h"
int main() {
SqStack S;
int cur,x;
InitStack(S);
for (int i = 1; i < 5; i++) {
Push(S, i * 10); // 10 20 30 40
}
Pop(S, cur);
printf("Pop栈顶元素为: %d \n", cur); // 40
PrintStack(S); // 30 20 10
Peek(S, x);
printf("Peek栈顶元素为: %d \n", x); // 30
PrintStack(S); // 30 20 10
return 0;
}
测试代码截图
共享栈
SharedStack,h
#define _CRT_SECURE_NO_WARNINGS
#define MAXSIZE 16
typedef int ElemType;
typedef struct {
int data[MAXSIZE]; //共享栈的数据
int top1; //第一个栈的栈顶
int top2; //第二个栈的栈顶
}SharedStack;
//初始化共享栈
void initStack(SharedStack& S);
//判断第一个栈是否已满
bool isFull1(SharedStack S);
//判断第二个栈是否已满
bool isFull2(SharedStack S);
//判断第一个栈是否为空
bool isEmpty1(SharedStack S);
//判断第二个栈是否为空
bool isEmpty2(SharedStack S);
// 在第一个栈中入栈元素e
void push1(SharedStack& S, ElemType e);
// 在第二个栈中入栈元素e
void push2(SharedStack& S, ElemType e);
// 在第一个栈中出栈
ElemType pop1(SharedStack& S);
// 在第二个栈中出栈
ElemType pop2(SharedStack& S);
// 获取第一个栈顶元素
ElemType peek1(SharedStack S);
// 获取第二个栈顶元素
ElemType peek2(SharedStack S);
//打印第一个栈中的元素值
void printStack1(SharedStack S);
//打印第二个栈中的元素值
void printStack2(SharedStack S);
//打印共享栈中所有的元素值
void printStack(SharedStack S);
SharedStack.cpp
这里只写了top1 = -1 top2 = maxdize的情况。
#include<stdio.h>
#include"sharedStack.h"
#include<stdlib.h>
//初始化共享栈
void initStack(SharedStack& S) {
for (int i = 0; i < MAXSIZE; i++) { //初始化所有元素为0,防止乱指针
S.data[i] = 0;
}
S.top1 = -1; //第一个栈的栈顶指针初始化指向0
S.top2 = MAXSIZE;//第一个栈的栈顶指针初始化指向MAXSIZE-1
}
//判断第一个栈是否已满
bool isFull1(SharedStack S) {
return S.top1 + 1 == S.top2; //top1指针加1等于top2
}
//判断第二个栈是否已满
bool isFull2(SharedStack S) {
return S.top2 - 1 == S.top1;
}
//判断第一个栈是否为空
bool isEmpty1(SharedStack S) {
return S.top1 == -1;
}
//判断第二个栈是否为空
bool isEmpty2(SharedStack S) {
return S.top2 == MAXSIZE;
}
// 在第一个栈中入栈元素e
void push1(SharedStack& S, ElemType e) {
if (!isFull1(S)) {
S.data[++S.top1] = e;
}
}
// 在第二个栈中入栈元素e
void push2(SharedStack& S, ElemType e) {
if (!isFull2(S)) {
S.data[--S.top2] = e;
}
}
// 在第一个栈中出栈
ElemType pop1(SharedStack& S) {
if (!isEmpty1(S)) {
ElemType x = S.data[S.top1];
S.data[S.top1] = 0; // pop完之后给他置为0
S.top1--;
return x;
}
return -999; //代表空栈
}
// 在第二个栈中出栈
ElemType pop2(SharedStack& S) {
if (!isEmpty2(S)) {
ElemType x = S.data[S.top2];
S.data[S.top2] = 0; // pop完之后给他置为0
S.top2++;
return x;
}
return -999; //代表空栈
}
// 查看第一个栈栈顶元素
ElemType peek1(SharedStack S) {
if (!isEmpty1(S)) {
return S.data[--S.top1];
}
return -999;//代表空栈返回空
}
// 查看第二个栈栈顶
ElemType peek2(SharedStack S) {
if (!isEmpty2(S)) {
return S.data[++S.top2];
}
return -999;
}
//打印第一个栈中的元素值
void printStack1(SharedStack S) {
for (int i = S.top1; i >= 0; i--) {
printf("%d ", S.data[i]);
}
printf("\n");
}
//打印第二个栈中的元素值
void printStack2(SharedStack S) {
for (int i = S.top2; i <= MAXSIZE - 1; i++) {
printf("%d ", S.data[i]);
}
printf("\n");
}
//打印共享栈中所有的元素值
void printStack(SharedStack S) {
for (int i = 0; i < MAXSIZE; i++) {
printf("%d ", S.data[i]);
}
printf("\n");
}
测试main.cpp
#include<stdio.h>
#include"sharedStack.h"
int main() {
SharedStack S;
initStack(S);
for (int i = 0; i < 10; i++) {
push1(S, i);
}
printf("第一个栈中:");
printStack1(S);
//-----------------------
for (int i = 20; i < 25; i++) {
push2(S, i);
}
printf("第二个栈中:");
printStack2(S);
//------------------------
printf("整个栈中:");
printStack(S);
printf("===============================\n");
for (int i = 0; i < 5; i++) {
ElemType x = pop1(S);
printf("当前出栈的元素为:%d \n", x);
}
printf("pop后第一个栈中:");
printStack1(S);
printf("pop后整个栈中:");
printStack(S);
return 0;
}
测试代码截图
链栈
LinkStack.h
#pragma once
typedef int ElemType;
/*
链栈数据结构
*/
typedef struct LNode {
ElemType data; //数据域
LNode* next; // 指针域
}LNode,*LinkedStack;
// 初始化栈
void initLinkedStack(LinkedStack& L);
// 判断栈是否空
bool isEmptyStack(LinkedStack L);
// 进栈
void push(LinkedStack& L, ElemType x);
// 出栈
ElemType pop(LinkedStack& L);
// 读取栈顶元素
ElemType peek(LinkedStack L);
// 打印输出栈
void printStack(LinkedStack L);
// 栈的长度
int getSackLen(LinkedStack L);
LinkedStack.cpp
#include<stdio.h>
#include<stdlib.h>
#include"linkedStack.h"
// 初始化栈
void initLinkedStack(LinkedStack& L) {
L = (LNode*)malloc(sizeof(LNode)); //建立一个头结点
if (L) {
L->next = NULL;
L->data = 0; //头结点的数据域用来存放链表的长度
}
}
// 判断栈是否空
bool isEmptyStack(LinkedStack L) {
return L->next == NULL;
//return L->data == 0;
}
// 进栈(相当于使用头插法向链表中插入元素)
void push(LinkedStack& L, ElemType x) {
LNode* newNode = (LNode*)malloc(sizeof(LNode)); //申请一个新节点
newNode->data = x;
newNode->next = L->next; //头插法创建节点
L->next = newNode;
L->data++; // 表长+1
}
// 出栈(相当于删除链表的第一个元素)
ElemType pop(LinkedStack& L) {
if (isEmptyStack(L)) return -1;
LNode* removed = L->next;
L->next = removed->next;
ElemType x = removed->data;
free(removed); //释放被删除的节点
L->data--; //表长-1
return x;
}
// 读取栈顶元素
ElemType peek(LinkedStack L) {
if (isEmptyStack(L)) return -1;
return L->next->data;
}
// 打印输出栈
void printStack(LinkedStack L) {
if (L == NULL || L->next == NULL) {
return;
}
LNode* p = L->next;
while (p)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int getSackLen(LinkedStack L) {
return L->data;
}
测试main.cpp
#include<stdio.h>
#include"linkedStack.h"
int main() {
LinkedStack L;
//----初始化链栈-----
initLinkedStack(L);
//----往链栈中压入10个元素
for (int i = 0; i < 10; i++) {
push(L, i);
}
printf("测试入栈操作:");
printStack(L); // 9 8 7 6 5 4 3 2 1 0
printf("栈的长度为:%d \n", getSackLen(L)); // 10
//-------------------------------
for (int i = 0; i < 5; i++) {
pop(L);
}
printf("测试出栈操作:");
printStack(L); //4 3 2 1 0
printf("栈的长度为:%d \n", getSackLen(L)); // 5
return 0;
}
测试截图
队列
顺序队列
SqQueue.h
#pragma once
#define MAXSIZE 8
typedef int ElemType;
/*
定义顺序队列的结构体
*/
typedef struct {
ElemType data[MAXSIZE]; // 数据域
int front; // 队头指针
int rear; // 队尾指针
}SqQueue;
//初始化队列
void initQueue(SqQueue& Q);
// 判断队列是否为空
bool isEmptyQueue(SqQueue Q);
// 判断队列是否满
bool isFullQueue(SqQueue Q);
// 元素e入队
void enQueue(SqQueue& Q, ElemType e);
// 队头元素出队
ElemType deQueue(SqQueue& Q);
// 获取队首元素
ElemType getHead(SqQueue Q);
// 打印队列元素
void printQueue(SqQueue Q);
SqQueue.cpp
#include<cstdio>
#include<cstdlib>
#include"SqQueue.h"
//初始化队列
void initQueue(SqQueue& Q) {
for (int i = 0; i < MAXSIZE; i++) {
Q.data[i] = 0; //初始化队列数据全部为0,防止脏数据
}
Q.front = 0; //初始化队头指针指向0索引
Q.rear = 0; //初始化队尾指针指向0索引
}
// 判断队列是否为空
bool isEmptyQueue(SqQueue Q) {
return Q.front == Q.rear; //如果队头和队尾指向同一个位置,说明队列为空
}
bool isFullQueue(SqQueue Q) {
return (Q.rear + 1) % MAXSIZE == Q.front;
}
// 元素e入队
void enQueue(SqQueue& Q, ElemType e) {
if (!isFullQueue(Q)) {
Q.data[Q.rear] = e; //在尾指针位置插入元素e后,尾指针后移,始终指向待入队位置
Q.rear++;
}
return;
}
// 队头元素出队
ElemType deQueue(SqQueue& Q) {
if (!isEmptyQueue(Q)) {
ElemType x = Q.data[Q.front];
Q.front++;
return x;
}
return -999; //队列为空
}
// 获取队首元素
ElemType getHead(SqQueue Q) {
if (!isEmptyQueue(Q)) {
return Q.data[Q.front];
}
return -999;
}
// 打印队列
void printQueue(SqQueue Q) {
if (isEmptyQueue(Q)) {
printf("队列为空!");
return;
}
int pos = Q.front;
while (pos != Q.rear)
{
printf("%d ", Q.data[pos]);
pos++;
}
printf("\n");
printf("Q.front = %d ,Q.rear = %d\n", Q.front, Q.rear);
}
main.cpp
#include<cstdio>
#include<cstdlib>
#include"SqQueue.h"
int main() {
SqQueue Q;
initQueue(Q);
//====测试入队==============
for (int i = 0; i < 6; i++) {
enQueue(Q,i); // 0 1 2 3 4 5
}
printQueue(Q); // 0 1 2 3 4 5
//====测试出队===============
for (int i = 0; i < 2; i++) {
ElemType x = deQueue(Q);
printf("当前出队元素值:%d \n", x); // 0 1
}
printQueue(Q); // 2 3 4 5
//====测试获取队头元素==========
printf("当前队头元素为:%d \n", getHead(Q));
return 0;
}
测试截图
循环队列(三种方式)
Queue.h
方式一:牺牲一个存储空间在区分队空和对满;
约定当尾指针的下一个位置是头指针时,队满
队满:(Q.rear + 1)% MAXSIZE = Q.front
队空:Q.front = Q.rear
方式二:新增一个数据成员,专门用于表示数据个数size
队满:Q.size = MAXSIZE
队空:Q.size = 0
方式三:新增一个数据成员tag,用来标志队空和队满
队满:Q.tag = 1 && Q.front = Q.rear
队空:Q.tag = 0 && Q.front = Q.rear
#define MAXSIZE 8
typedef int ElemType;
/*
实现循环队列的三种方式
方式一:牺牲一个存储空间在区分队空和对满;
约定当尾指针的下一个位置是头指针时,队满
队满:(Q.rear + 1)% MAXSIZE = Q.front
队空:Q.front = Q.rear
方式二:新增一个数据成员,专门用于表示数据个数size
队满:Q.size = MAXSIZE
队空:Q.size = 0
方式三:新增一个数据成员tag,用来标志队空和队满
队满:Q.tag = 1 && Q.front = Q.rear
队空:Q.tag = 0 && Q.front = Q.rear
*/
typedef struct {
ElemType data[MAXSIZE]; // 数据域
int front; // 队头指针
int rear; // 队尾指针
int size; // 队列大小
int tag; // 标志位
} SqQueue;
// 初始化队列
void initQueue(SqQueue& Q);
// 判断队列是否为空
bool isEmptyQueue(SqQueue Q);
// 判断队列是否已满
bool isFullQueue(SqQueue Q);
// 入队操作
void enQueue(SqQueue& Q, ElemType e);
//队头元素出队,并返回
ElemType deQueue(SqQueue& Q);
//获取队列长度
int getSize(SqQueue Q);
//获取队首元素
ElemType getHead(SqQueue Q);
//打印队列元素
void printQueue(SqQueue Q);
Queue.cpp
#include<cstdio>
#include<cstdlib>
#include"Queue.h"
// 初始化队列
void initQueue(SqQueue& Q) {
//对数据元素进行初始化,防止出现脏数据
for (int i = 0; i < MAXSIZE; i++) {
Q.data[i] = 0;
}
// 方式一
Q.front = 0;
Q.rear = 0;
// 方式二
Q.size = 0;
// 方式三
Q.tag = 0;
}
// 判断队列是否为空
bool isEmptyQueue(SqQueue Q) {
//return Q.front == Q.rear; // 方式一
return Q.size == 0; // 方式二
//return Q.tag == 0 && Q.front == Q.rear; // 方式三
}
// 判断队列是否已满
bool isFullQueue(SqQueue Q) {
//return (Q.rear + 1) % MAXSIZE == Q.front; //方式一
return Q.size == MAXSIZE; // 方式二
//return Q.tag == 1 && Q.front == Q.rear; // 方式三
}
// 入队操作
void enQueue(SqQueue& Q, ElemType e) {
if (isFullQueue(Q)) {
return;
}
// 方式一
Q.data[Q.rear] = e;
Q.rear = (Q.rear + 1) % MAXSIZE;
// 方式二
Q.size++;
// 方式三
//if (Q.rear == Q.front) {
// Q.tag = 1;
//}
}
//队头元素出队,并返回
ElemType deQueue(SqQueue& Q) {
if (isEmptyQueue(Q)) {
return -999;
}
// 方式一
ElemType x = Q.data[Q.front];
//Q.data[Q.front] = 0; //出队完之后置为0
Q.front = (Q.front + 1) % MAXSIZE;
// 方式二
//Q.size--;
// 方式三
/*
这里如果这样写的话,会有一个bug,当第一次入队的元素个数等于MAXSIZE的话,
因为在队满的时候,我已经将tag=1,所以当我测试出队两个元素后,队列没空,此时的tag还是等于1,
所以当我出队后再次执行 getSize(Q)的时候,还是会执行Q.tag = 1,所以长度又变成了MAXSIZE大小,
所以每次出队后,都要把Q.tag = 0,队列空的时候,再加上(Q.tag = 0 && Q.rear == Q.front)。
if (Q.front == Q.rear) {
Q.tag = 0;
}
*/
Q.tag = 0;
return x;
}
//获取队列长度
int getSize(SqQueue Q) {
//return (Q.rear - Q.front + MAXSIZE) % MAXSIZE; // 方式一、二、三均适用
return Q.size; //方式二
}
// 获取队首元素
ElemType getHead(SqQueue Q) {
if (isEmptyQueue(Q)) {
return -999;
}
return Q.data[Q.front];
}
//打印队列元素
void printQueue(SqQueue Q) {
if (isEmptyQueue(Q)) {
printf("队列为空\n");
return;
}
printf("队列内容: ");
int len = getSize(Q);
int pos = Q.front;
while (len > 0) {
printf("%d ", Q.data[pos]);
pos = (pos + 1) % MAXSIZE; // 循环往后+1
len--;
}
printf("\n");
}
main.cpp
#include<cstdio>
#include<cstdlib>
#include"Queue.h"
int main() {
SqQueue Q;
initQueue(Q); // 初始时将所有元素置为了0
// 测试入队操作 (MAXSIZE==8)
for (int i = 1; i <= MAXSIZE; i++) {
enQueue(Q, i);
}
// 打印队列内容
printQueue(Q); // 方法一:1 2 3 4 5 6 7 方法二:1 2 3 4 5 6 7 8 方法三:1 2 3 4 5 6 7 8
//测试获取队列长度
printf("当前队列的长度为:%d \n", getSize(Q)); // 方法一:7(因为牺牲了一个存储单元) 方法二:8 方法三:8
// 测试出队操作
for (int i = 1; i <= 2; i++) {
ElemType e = deQueue(Q);
printf("当前出队的元素为:%d \n",e); // 当前出队的元素为:1 当前出队的元素为:2
}
// 打印出队后的队列内容
printQueue(Q); // 方法一:3 4 5 6 7 方法二:3 4 5 6 7 8 方法三:3 4 5 6 7 8
// 测试获取队头元素
printf("当前队列的队头元素为:%d \n", getHead(Q)); // 方法一:3 方法二:3 方法三:3
return 0;
}
测试截图
测试当队中元素等于MAXSIZE时的情况
链队列
LinkedQueue.h
#pragma once
typedef int ElemType;
//结点结构
typedef struct LNode {
ElemType data;
LNode* next;
}LNode;
//队列结构
typedef struct {
LNode* front; //队列的队头指针
LNode* rear; //队列的队尾指针
int size; //队列大小
}LinkedQueue;
//初始化队列
void initQueue(LinkedQueue& Q);
//判断队列是否为空
bool isEmpty(LinkedQueue Q);
//元素x入队
void enQueue(LinkedQueue& Q, ElemType x);
//队头元素出队,并返回
ElemType deQueue(LinkedQueue& Q);
//获取队首元素
ElemType getHead(LinkedQueue Q);
//获取队列长度
int getSize(LinkedQueue Q);
//打印队列元素
void printQueue(LinkedQueue Q);
LinkedQueue.cpp
#include<cstdio>
#include<cstdlib>
#include"LinkedQueue.h"
//初始化队列
void initQueue(LinkedQueue& Q) {
Q.front = NULL;
Q.rear = NULL;
Q.size = 0;
}
//判断队列是否为空
bool isEmpty(LinkedQueue Q) {
if (Q.front == NULL && Q.rear == NULL) {
return true;
}
else {
return false;
}
}
//元素x入队
void enQueue(LinkedQueue& Q, ElemType x) {
LNode* node = (LNode*)malloc(sizeof(LNode));
node->data = x;
node->next = NULL;
//如果是入队的第一个元素
if (Q.front == NULL && Q.rear == NULL) {
Q.front = node;
Q.rear = node;
}
else {
Q.rear->next = node; //最后一个结点的next指向新结点元素
Q.rear = node; //rear指向新结点
}
Q.size++; //队列长度+1
}
//队头元素出队,并返回
ElemType deQueue(LinkedQueue& Q) {
if (isEmpty(Q)) {
return -999;
}
LNode* removed = Q.front; //记录队头(即被删除元素结点以便释放空间)
ElemType x = removed->data; //接收队头元素以便返回
Q.front = Q.front->next; //队头后移
//如果已经出队直到没元素了,别忘了也让Q.rear = null
if (Q.front == NULL) {
Q.rear = Q.front;
}
free(removed); //释放删除结点空间
Q.size--; //队列长度-1
return x;
}
//获取队首元素
ElemType getHead(LinkedQueue Q) {
if (isEmpty(Q)) {
return -999;
}
return Q.front->data;
}
//获取队列长度
int getSize(LinkedQueue Q) {
return Q.size;
}
//打印队列元素
void printQueue(LinkedQueue Q) {
LNode* p = Q.front;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
main.cpp
#include<cstdio>
#include<cstdlib>
#include"LinkedQueue.h"
int main() {
LinkedQueue Q;
initQueue(Q);
// 测试入队
for (int i = 1; i <= 8; i++) {
enQueue(Q, i);
}
printQueue(Q);
printf("=================\n");
// 测试出队
for (int j = 0; j < 2; j++) {
ElemType x = deQueue(Q);
printf("当前出队元素:%d \n",x);
}
printQueue(Q);
printf("=================\n");
// 测试获取队列长度
printf("当前队列的长度为:%d\n", getSize(Q));
printf("=================\n");
// 测试获取队头
printf("当前队列的队头为:%d \n", getHead(Q));
return 0;
}
测试截图
双端队列(带头节点双链表实现)
DNode.h
#pragma once
//用双链表(带头结点)实现双端队列
typedef int ElemType;
typedef struct DNode {
ElemType data; //数据域
DNode* prior; //指向前驱结点的指针域
DNode* next; //指向后继结点的指针域
}DNode;
typedef struct {
DNode* front; //队头指针
DNode* rear; //队尾指针
int size; //队列长度
}DeQueue;
//初始化双端队列
void initDeQueue(DeQueue& Q);
//判断队列是否为空
bool isEmpty(DeQueue Q);
//向队头添加元素e
void pushHead(DeQueue& Q, ElemType e);
//从队头移除元素并返回
ElemType popHead(DeQueue& Q);
//向队尾添加元素e
void pushTail(DeQueue& Q, ElemType e);
//从队尾删除元素并返回
ElemType popTail(DeQueue& Q);
//从前往后打印队列元素
void printDeQueuefromHead(DeQueue Q);
//从后往前打印队列元素
void printDeQueuefromTail(DeQueue Q);
DNode.cpp
#include<cstdio>
#include<cstdlib>
#include"DNode.h"
//初始化双端队列(带头节点)
void initDeQueue(DeQueue& Q) {
DNode* head = (DNode*)malloc(sizeof(DNode)); //申请头结点
//初始化头结点
head->next = NULL;
head->prior = NULL;
Q.front = head; //队列的头指针和尾指针都指向头结点
Q.rear = head;
Q.size = 0; //队列大小初始化为0
}
//判断队列是否为空
bool isEmpty(DeQueue Q) {
return Q.size == 0;
}
//向队头添加元素e
void pushHead(DeQueue& Q, ElemType e) {
DNode* node = (DNode*)malloc(sizeof(DNode));
node->data = e;
node->next = NULL;
node->prior = NULL;
if (Q.front == Q.rear) { // 如果此时队列还无元素,插入第一个元素时
Q.front->next = node; // 头结点的后继——>新节点
node->prior = Q.front; // 新节点的前驱——>头结点
Q.rear = node; // 尾节点后移
}
// 如果不是第一个节点,
else
{
node->next = Q.front->next; // 新节点的后继指向头节点的后继
Q.front->next->prior = node; // 头节点的后继的前驱是新节点
Q.front->next = node; // 头结点的后继是新节点
node->prior = Q.front; // 新节点的前驱是头结点
}
Q.size++; //队列长度+1
}
//从队头移除元素并返回
ElemType popHead(DeQueue& Q) {
if (isEmpty(Q)) {
return -999; //代表队列为空
}
DNode* removed = Q.front->next; //第一个节点就是头结点的next
ElemType x = removed->data; // 记录一下被删除的节点
if (removed->next == NULL) { //队列中只有一个节点
Q.front->next = NULL; //直接让头结点的next指向NULL
Q.rear = Q.front; // 再让队尾指向队头表示为空了
}
else
{
Q.front->next = removed->next; //头结点的后继指向被删除结点的后继
removed->next->prior = Q.front; //被删除结点的后继的前序指向头结点
}
free(removed); //释放空间队列长度-1
Q.size--;
return x;
}
//向队尾添加元素e
void pushTail(DeQueue& Q, ElemType e) {
DNode* node = (DNode*)malloc(sizeof(DNode));
node->data = e;
node->next = NULL;
node->prior = Q.rear; // 新节点的前驱指向尾指针
Q.rear->next = node; //队尾指针的next指向新结点
Q.rear = node; // 队尾后移
Q.size++;
}
//从队尾删除元素并返回
ElemType popTail(DeQueue& Q) {
if (isEmpty(Q)) {
return -999;
}
DNode* removed = Q.rear;
ElemType x = removed->data;
Q.rear->prior->next = NULL; //队尾指针结点的前序的后继指向空,即倒数第二个结点的next指向空
Q.rear = Q.rear->prior; //队尾指针来到倒数第二个结点处
free(removed); //释放最后一个结点空间
Q.size--;
return x;
}
//从前往后打印队列元素
void printDeQueuefromHead(DeQueue Q) {
if (isEmpty(Q)) {
return;
}
DNode* p = Q.front->next;
printf("从前到后:");
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
//从后往前打印队列元素
void printDeQueuefromTail(DeQueue Q) {
if (isEmpty(Q)) {
return;
}
DNode* p = Q.rear;
printf("从后到前:");
while (p != Q.front) {
printf("%d ", p->data);
p = p->prior;
}
printf("\n");
}
main.cpp
#include<cstdio>
#include<cstdlib>
#include"DNode.h"
int main() {
DeQueue Q;
initDeQueue(Q);
printf("=========头插法===========\n");
//测试从队头插入元素
for (int i = 1; i <= 8; i++) {
pushHead(Q, i);
}
// 从前往后打印
printDeQueuefromHead(Q);
// 从后往前打印
printDeQueuefromTail(Q);
// 测试从队头移除元素
for (int j = 0; j < 2; j++) {
ElemType x = popHead(Q);
printf("当前移除的元素:%d \n", x);
}
// 从前往后打印
printDeQueuefromHead(Q);
// 从后往前打印
printDeQueuefromTail(Q);
printf("\n=========尾插法============\n");
// 测试从队尾插入新元素
DeQueue Q2;
initDeQueue(Q2);
for (int i = 1; i <= 8; i++) {
pushTail(Q2, i);
}
// 从前往后打印
printDeQueuefromHead(Q2);
// 从后往前打印
printDeQueuefromTail(Q2);
// 测试从队头移除元素
for (int j = 0; j < 2; j++) {
ElemType x = popTail(Q2);
printf("当前移除的元素:%d \n", x);
}
// 从前往后打印
printDeQueuefromHead(Q2);
// 从后往前打印
printDeQueuefromTail(Q2);
return 0;
}
测试截图