数据结构——栈和队列

1 定义

一种特殊的线性表,只允许固定的一端插入或删除元素,这一端称为栈顶,另一端是栈底。栈中的数据元素遵守后进先出原则。

2 栈的实现

使用数组和链式结构实现都可以
(1)数组栈:
数据表尾插尾删效率高
(2)链式栈:
①尾作为栈顶,尾插尾删,单向链表效率低,双向链表适用
②头作为栈顶,头插头删,单向链表也适用

3 实现代码

// Stack.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int STDataType;
typedef struct Stack {
	STDataType *a;
	int top;
	int capacity;
}ST;

// 初始化栈
void StackInit(ST* ps);
// 销毁栈
void StackDestroy(ST* ps);
// 入栈
void StackPush(ST* ps, STDataType x);
// 出栈
void StackPop(ST* ps);
// 返回栈顶元素
STDataType StackTop(ST* ps);
// 判断栈是否为空
bool StackEmpty(ST* ps);
// 查询栈数据个数
int StackSize(ST* ps);
// Stack.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Stack.h"
//typedef int STDataType;
//typedef struct Stack {
//	STDataType* a;
//	int top;
//	int capacity;
//}ST;

// 初始化栈
void StackInit(ST* ps) {
	assert(ps);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}
// 销毁栈
void StackDestroy(ST* ps) {
	assert(ps);
	free(ps->a);

	ps->a = NULL;
	ps->top = ps->capacity = 0;
}
// 入栈
void StackPush(ST* ps, STDataType x) {
	assert(ps);
	if (ps->capacity == ps->top) {
		int newcapa = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp = realloc(ps->a, sizeof(STDataType) * newcapa);
		if (tmp == NULL) {
			printf("realloc fail\n");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = newcapa;
	}
	ps->a[ps->top] = x;
	ps->top++;
}
// 出栈
void StackPop(ST* ps) {
	assert(ps);
	assert(ps->top > 0);
	ps->top--;
}
// 返回栈顶元素
STDataType StackTop(ST* ps) {
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->a[ps->top - 1];
}
// 判断栈是否为空
bool StackEmpty(ST* ps) {
	assert(ps);
	return ps->top == 0;
}
// 查询栈数据个数
int StackSize(ST* ps) {
	assert(ps);
	return ps->top;
}
// Test.c
#define _CRT_SECURE_NO_WARNINGS 1

#include "Stack.h"

void TestStack1()
{
	ST st;
	StackInit(&st);

	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);
	StackPush(&st, 4);

	StackPop(&st);
	StackPop(&st);
	StackPop(&st);
	//StackPop(&st);
	//StackPop(&st);
	printf("%d", StackTop(&st));

	StackDestroy(&st);
}

void TestStack2()
{
	ST st;
	StackInit(&st);

	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);
	StackPush(&st, 4);

	printf("%d ", StackTop(&st));
	StackPop(&st);
	printf("%d ", StackTop(&st));
	StackPop(&st);

	StackPush(&st, 5);
	StackPush(&st, 6);


	while (!StackEmpty(&st))
	{
		printf("%d ", StackTop(&st));
		StackPop(&st);
	}

	StackDestroy(&st);
}

int main()
{
	TestStack1();
	printf("\n");
	TestStack2();

	return 0;
}

4 运行结果

在这里插入图片描述

队列

1 定义

只允许在一端进行插入数据操作(入队列),在另一端进行删除数据操作(出队列)的特殊线性表,进行插入操作的一端称为队尾,进行删除操作的一端称为队头。队列中的数据遵守先进先出原则。

2 队列的实现

使用链式结构实现效率较高
(1)数组队列
入队列或出队列一项在数组尾进行,则另一项操作在数组头进行,一定要移动数组所有数据,时间复杂度为O(n2)
(2)链式队列
头插尾删或头删尾插,时间复杂度为O(n)
增加一个尾指针,时间复杂度O(1)

3 实现代码

// Queue.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

typedef int QDataType;
typedef struct QueueNode {
	QDataType a;
	struct QueueNode* next;
}QueueNode;

typedef struct Queue {
	QueueNode* head;
	QueueNode* tail;
}Queue;

// 初始化
void QueueInit(Queue* pq);
// 销毁
void QueueDestroy(Queue* pq);
// 入队列
void QueuePush(Queue* pq, QDataType x);
// 出队列
void QueuePop(Queue* pq);
// 查询队头
QDataType QueueFront(Queue* pq);
// 查询队尾
QDataType QueueBack(Queue* pq);
// 队列数据个数
int QueueSize(Queue* pq);
// 判空
bool QueueEmpty(Queue* pq);
// Queue.c
#include "Queue.h"

//typedef int QDataType;
//typedef struct QueueNode {
//	QDataType a;
//	QueueNode* next;
//}QueueNode;
//
//typedef struct Queue {
//	QueueNode* head;
//	QueueNode* tail;
//}Queue;

// 初始化
void QueueInit(Queue* pq) {
	assert(pq);
	pq->head = NULL;// 队头,删除
	pq->tail = NULL;// 队尾,插入
}
// 销毁
void QueueDestroy(Queue* pq) {
	assert(pq);
	QueueNode* cur = pq->head;

	while (cur) {
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
	//free(pq->head);
	//free(pq->tail);
}
// 入队列
void QueuePush(Queue* pq, QDataType x) {
	assert(pq);
	QueueNode* newNode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newNode) {
		newNode->a = x;
		newNode->next = NULL;

		// 插入分空链和非空
		if (!pq->head) {
			pq->head = pq->tail = newNode;
		}
		else {
			//newNode->next = pq->head;
			//pq->head = newNode;
			pq->tail->next = newNode;
			pq->tail = newNode;
		}
	}
}
// 出队列
void QueuePop(Queue* pq) {
	assert(pq);
	assert(!QueueEmpty(pq));
	QueueNode* next = pq->head->next;
	free(pq->head);
	pq->head = next;
	if (pq->head == NULL)
	{
		pq->tail = NULL;
	}
}
// 查询队头
QDataType QueueFront(Queue* pq) {
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->head->a;
}
// 查询队尾
QDataType QueueBack(Queue* pq) {
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->tail->a;
}
// 队列数据个数
int QueueSize(Queue* pq) {
	assert(pq);
	QueueNode* node = pq->head;
	int n = 0;
	while (node) {
		node = node->next;
		n++;
	}
	return n;
}
// 判空
bool QueueEmpty(Queue* pq) {
	assert(pq);
	return pq->head == NULL;
}
// Test.c
#include "Queue.h"
void QueueTest1() {
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	printf("队头:%d\n", QueueFront(&q));
	printf("队尾:%d\n", QueueBack(&q));
	printf("队列长度:%d\n", QueueSize(&q));
	
	QueuePop(&q);
	printf("队头:%d\n", QueueFront(&q));
	printf("队尾:%d\n", QueueBack(&q));
	printf("队列长度:%d\n", QueueSize(&q));
	QueuePop(&q);
	QueuePop(&q);
	printf("队列长度:%d\n", QueueSize(&q));

	QueueDestroy(&q);
}
void QueueTest2() {
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 4);
	QueuePush(&q, 5);
	QueuePush(&q, 6);
	printf("队头:%d\n", QueueFront(&q));
	printf("队尾:%d\n", QueueBack(&q));
	printf("队列长度:%d\n", QueueSize(&q));
	
	while (!QueueEmpty(&q)) {
		printf("%d\n", QueueFront(&q));
		QueuePop(&q);
	}

	QueueDestroy(&q);
}
int main() {
	QueueTest1();
	printf("\n");
	QueueTest2();

	return 0;
}

4 运行结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值