栈和队列总结

1.栈

1.1栈的概念和结构

一种特殊的线性表,只允许在某一端插入或删除数据,这一端被称为栈顶,另一端称为栈底,
由于这种特征,所以栈具有先进后出的性质.
在这里插入图片描述
因为栈的操作只有入栈和出栈,都是都是在栈顶操作,并不需要挪动数据,所以采用顺序表结构比较合适

1.2栈的功能实现

1.2.1栈的结构定义
typedef int STData;
typedef struct Stack {
	STData* _a;
	size_t _top;//栈顶的下一个元素下标,也是栈里的元素数量
	size_t _capacity;
}Stack;
1.2.2初始化栈
//初始化栈
void StackInit(Stack* ps) {
	assert(ps);
	ps->_capacity = 4;
	ps->_a = (STData*)malloc(sizeof(STData) * ps->_capacity);
	ps->_top = 0;
}
1.2.3销毁栈
//销毁栈
void StackDestroy(Stack* ps) {
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->_capacity = ps->_top = 0;
}
1.2.4入栈
//入栈
void StackPush(Stack* ps, STData x) {
	assert(ps);
	//如果栈满了需要增加容量
	if (ps->_top == ps->_capacity) {
		ps->_capacity *= 2;
		STData* tmp = realloc(ps->_a, sizeof(STData) * ps->_capacity);
		if (tmp == NULL) {
			perror("realloc");
			exit(-1);
		}
		ps->_a = tmp;
	}
	ps->_a[ps->_top] = x;
	ps->_top++;
}
1.2.5出栈
//出栈
void StackPop(Stack* ps) {
	assert(ps && ps->_top > 0);
	ps->_top--;
}
1.2.6获取栈顶元素
//获取栈顶元素
STData StackTop(Stack* ps) {
	assert(ps);
	return ps->_a[ps->_top - 1];
}
1.2.7判断栈是否为空
//判断栈是否为空
bool StackEmpty(Stack* ps) {
	assert(ps);
	return ps->_top == 0;
}
1.2.8获取栈的长度
//获取栈的长度
size_t StackSize(Stack* ps) {
	assert(ps);
	return ps->_top;
}

1.3栈的实现代码

1.3.1Stack.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include<string.h>
typedef int STData;
typedef struct Stack {
	STData* _a;
	size_t _top;
	size_t _capacity;
}Stack;
//初始化栈
void StackInit(Stack* ps);
//销毁栈
void StackDestroy(Stack* ps);
//入栈
void StackPush(Stack* ps, STData x);
//出栈
void StackPop(Stack* ps);
//获取栈顶元素
STData StackTop(Stack* ps);
//判断栈是否为空
bool StackEmpty(Stack* ps);
//获取栈的长度
size_t StackSize(Stack* ps);
1.3.2Stack.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Stack.h"
//初始化栈
void StackInit(Stack* ps) {
	assert(ps);
	ps->_capacity = 4;
	ps->_a = (STData*)malloc(sizeof(STData) * ps->_capacity);
	ps->_top = 0;
}
//销毁栈
void StackDestroy(Stack* ps) {
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->_capacity = ps->_top = 0;
}
//入栈
void StackPush(Stack* ps, STData x) {
	assert(ps);
	if (ps->_top == ps->_capacity) {
		ps->_capacity *= 2;
		STData* tmp = realloc(ps->_a, sizeof(STData) * ps->_capacity);
		if (tmp == NULL) {
			perror("realloc");
			exit(-1);
		}
		ps->_a = tmp;
	}
	ps->_a[ps->_top] = x;
	ps->_top++;
}
//出栈
void StackPop(Stack* ps) {
	assert(ps && ps->_top > 0);
	ps->_top--;
}
//获取栈顶元素
STData StackTop(Stack* ps) {
	assert(ps);
	return ps->_a[ps->_top - 1];
}
//判断栈是否为空
bool StackEmpty(Stack* ps) {
	assert(ps);
	return ps->_top == 0;
}
//获取栈的长度
size_t StackSize(Stack* ps) {
	assert(ps);
	return ps->_top;
}
1.3.3Test.c
#include "Stack.h"
void TestStack() {
	Stack s;
	StackInit(&s);
	StackPush(&s, 1);
	StackPush(&s, 2);
	StackPush(&s, 3);
	StackPush(&s, 4);
	StackPop(&s);
	printf("%d\n", StackTop(&s));
	printf("%d\n ", StackSize(&s));
	StackDestroy(&s);
}
int main() {
	TestStack();
	return 0;
}

2.队列

2.1队列的概念和结构

队列也是一种也是的线性表结构,它只允许在一端插入数据,在另一端删除数据,插入元素的一端称为队尾,删除元素的一段称为队头,由于这种特性,它具有先进先出的特点。

在这里插入图片描述
由于队列需要在队头删除数据,如果用线性表结构删除数据时,需要将后面的数据往前挪,时间复杂度时O(N),而用链表只需要把头释放掉即可,所以链表更合适。

2.2队列的功能实现

2.2.1队列的结构定义

由于队列需要对头尾进行操作,一个队列保存队头和队尾指针。

typedef int QData;
typedef struct QueueNode {
	QData _a;
	struct QueueNode* _next;
}QueueNode;
typedef struct Queue {
	QueueNode* _head;
	QueueNode* _tail;
}Queue;
2.2.2初始化队列
//初始化队列
void QueueInit(Queue* pq) {
	assert(pq);
	pq->_head = pq->_tail = NULL;
}
2.2.3销毁队列
//销毁队列
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;
}
2.2.4入队
//入队
void QueuePush(Queue* pq, QData x) {
	assert(pq);
	QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));
	node->_a = x;
	node->_next = NULL;
	//如果队列里没有数据
	if (pq->_head == NULL) {
		pq->_head = pq->_tail = node;
	}
	//如果队列里有数据
	else {
		pq->_tail->_next = node;
		pq->_tail = node;
	}
}
2.2.5出队
//出队
void QueuePop(Queue* pq) {
	assert(pq);
	//当队列为空时不能出队
	assert(pq->_head != NULL);
	//如果队列只有一个数据时
	if (pq->_head->_next == NULL) {
		free(pq->_tail);
		pq->_head = pq->_tail = NULL;
	}
	//如果队列不只有一个数据时
	else {
		QueueNode* newHead = pq->_head->_next;
		free(pq->_head);
		pq->_head = newHead;
	}
	
}
2.2.6获取队头
//获取队头
QData QueueFront(Queue* pq) {
	assert(pq);
	assert(pq->_head != NULL);
	return pq->_head->_a;

}
2.2.7获取队尾
//获取队尾
QData QueueBack(Queue* pq) {
	assert(pq);
	assert(pq->_tail);
	return pq->_tail->_a;
}
2.2.8判断队列是否为空
//判断队列是否为空
bool QueueEmpty(Queue* pq) {
	assert(pq);
	return pq->_head == NULL;
}
2.2.9获取队列长度
//获取队的长度
size_t QueueSize(Queue* pq) {
	assert(pq);
	size_t size = 0;
	QueueNode* cur = pq->_head;
	while (cur) {
		size++;
		cur = cur->_next;
	}
	return size;
}

2.3队列的实现代码

2.3.1Queue.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include<string.h>
typedef int QData;
typedef struct QueueNode {
	QData _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, QData x);
//出队
void QueuePop(Queue* pq);
//获取队头
QData QueueFront(Queue* pq);
//获取队尾
QData QueueBack(Queue* pq);
//判断队列是否为空
bool QueueEmpty(Queue* pq);
//获取队的长度
size_t QueueSize(Queue* pq);

2.3.2Queue.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Queue.h"
//初始化队列
void QueueInit(Queue* pq) {
	assert(pq);
	pq->_head = 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;
}
//入队
void QueuePush(Queue* pq, QData x) {
	assert(pq);
	QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));
	node->_a = x;
	node->_next = NULL;
	if (pq->_head == NULL) {
		pq->_head = pq->_tail = node;
	}
	else {
		pq->_tail->_next = node;
		pq->_tail = node;
	}
}
//出队
void QueuePop(Queue* pq) {
	assert(pq);
	assert(pq->_head != NULL);
	if (pq->_head->_next == NULL) {
		free(pq->_tail);
		pq->_head = pq->_tail = NULL;
	}
	else {
		QueueNode* newHead = pq->_head->_next;
		free(pq->_head);
		pq->_head = newHead;
	}
	
}
//获取队头
QData QueueFront(Queue* pq) {
	assert(pq);
	assert(pq->_head != NULL);
	return pq->_head->_a;

}
//获取队尾
QData QueueBack(Queue* pq) {
	assert(pq);
	assert(pq->_tail);
	return pq->_tail->_a;
}
//判断队列是否为空
bool QueueEmpty(Queue* pq) {
	assert(pq);
	return pq->_head == NULL;
}
//获取队的长度
size_t QueueSize(Queue* pq) {
	assert(pq);
	size_t size = 0;
	QueueNode* cur = pq->_head;
	while (cur) {
		size++;
		cur = cur->_next;
	}
	return size;
}
2.3.3Test.c
#include "Queue.h"
void TestQueue() {
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);
	QueuePop(&q);
	printf("%d\n", QueueFront(&q));
	printf("%d\n", QueueBack(&q));
	printf("%d\n ", QueueSize(&q));
	QueueDestroy(&q);

}
int main() {
	TestQueue();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值