考研408数据结构基础代码(基于王道书)

线性表

顺序表

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;
}

测试截图
在这里插入图片描述

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值