栈和队列的实现

 目录 

1.栈

1.1栈的概念及结构

 1.2栈的实现

2.队列

2.1队列的概念及结构

2.2队列的实现


1.栈

1.1栈的概念及结构

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。 进行数据插入和删除操作的一端 称为栈顶,另一端称为栈底。 栈中的数据元素遵守后进先出 LIFO Last In First Out)的原则。 出栈是相对的,相对于同时在栈中的元素
压栈:栈的插入操作叫做进栈 / 压栈 / 入栈, 入数据在栈顶
出栈:栈的删除操作叫做出栈。 出数据也在栈顶

 1.2栈的实现

栈的实现一般可以使用 数组或者链表实现 ,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的 代价比较小。

 

 stack.h

#define  _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include <stdbool.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

typedef int STDatatype;
typedef struct Stack
{
	STDatatype* a;//用指针指向开辟空间的起始地址//用数组来存放数据,数组名就是首元素的地址
	              //存放相同类型数据就用素组,不同多种类型用结构体,类似顺序表
	int capacity;
	int top;   // 初始为0,表示栈顶位置下一个位置下标
}ST;

//注意栈的一个特点,都是对栈顶元素进行修改
//为了方便我们把数组的尾定义为栈顶

//初始化栈
void StackInit(ST* ps);
//销毁栈
void StackDestroy(ST* ps);
//入栈
void StackPush(ST* ps, STDatatype x);
//出栈
void StackPop(ST* ps);
//获取栈顶元素
STDatatype StackTop(ST* ps);

//布尔关键字bool,只需要两种状态就可以用
bool StackEmpty(ST* ps);
int StackSize(ST* ps);

stack.c

 注意出栈(只是把栈顶元素下标去掉)可以和找到栈顶元素进行搭配

#define  _CRT_SECURE_NO_WARNINGS 1
#include"stack.h"

void StackInit(ST* ps)
{
	assert(ps);
	ps->a == NULL;
	ps->capacity == 0;
	ps->top == 0;
	//另外一种写法
	//注释,ctrl+k+c
	/*解除注释,ctrl+k+u*/
	/*ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);
	if (ps->a == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

	ps->top = 0;
	ps->capacity = 4;*/
}

void StackDestroy(ST* ps)
{
	assert(ps);
	//free之后别忘记置空
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->top = 0;
}
//入栈
void StackPush(ST* ps, STDatatype x)
{
	assert(ps);
	//首先要检查是否还有空间
	if (ps->top == ps->capacity)
	{
		STDatatype* tmp = (STDatatype*)realloc(ps->a,ps->capacity*sizeof(STDatatype)*4);
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity *= 2;
	}
	ps->a[ps->top] = x;
	ps->top++;
}
//出栈
void StackPop(ST* ps)
{
	assert(ps);//指针不为空指针
	assert(!StackEmpty(ps));//栈也不为空

	ps->top--;//删除只需减去栈顶top
}
//找到栈顶元素
STDatatype StackTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));//一种意思

	return ps->a[ps->top - 1];
}
//布尔关键字bool,只需要两种状态就可以用
//空为真
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->a[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);
	StackPush(&st, 5);

	printf("size:%d\n", StackSize(&st)); // 不关心底层实现
	//printf("size:%d\n", st.top);  // 关心
	printf("size:%d\n", st.top + 1);  // 关心


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

	StackDestroy(&st);
}

int main()
{
	TestStack1();

	return 0;
}

2.队列

2.1队列的概念及结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out) 入队列:进行插入操作的一端称为 队尾 出队列:进行删除操作的一端称为 队头

2.2队列的实现

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数 组头上出数据,效率会比较低。

 Queue.h

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

//typedef 原来的  现在的
//使用的是现在的
//作用为一种数据类型定义一个新名字

//用链表来表示队列
typedef int QDataType;
typedef struct QListNode
{
	struct QListNode* next;
	QDataType data;
}QNode;
// 控制队列用头和尾指针,这是队列的结构
typedef struct Queue
{
	QNode* head;
	QNode* tail;
	int size;
}Queue;

// 初始化队列
void QueueInit(Queue* q);
// 队尾入队列
void QueuePush(Queue* q, QDataType x);
// 队头出队列
void QueuePop(Queue* q);
// 获取队列头部元素
QDataType QueueFront(Queue* q);
// 获取队列队尾元素
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q);
// 销毁队列
void QueueDestroy(Queue* q);

Queue.c

#define  _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"

// 初始化队列
void QueueInit(Queue* q)
{
	assert(q);
	q->head = NULL;
	q->tail = NULL;
	q->size = 0;
}
// 队尾入队列
void QueuePush(Queue* q, QDataType x)
{
	assert(q);
	QNode* node = (QNode*)malloc(sizeof(QNode));
	//用malloc开辟空间一定不要忘记判断
	if (node == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	node->data = x;
	node->next = NULL;
	if (q->tail == NULL)//如果带头就不需要判断直接链接
	{
		q->head = q->tail = node;
	}
	else
	{
		q->tail->next = node;//链接
		q->tail = node;//后移
	}
	q->size++;
}
// 队头出队列
void QueuePop(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));
	//考虑特殊情况只有一个节点
	if (q->head->next == NULL)
	{
		q->head = q->tail = NULL;
	}
	else
	{
		Queue* del = q->head;
		q->head = q->head->next;
		free(del);//通常free之后要置空,这里不需要置空是因为del是一个局部变量出作用域会销毁
	}
	q->size--;
}
// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
	assert(q);//q不能为空指针
	assert(!QueueEmpty(q));//这个队列要不为空
	return q->head->data;
}
// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
	assert(q);//q不能为空指针
	assert(!QueueEmpty(q));//这个队列要不为空
	return q->tail->data;
}
// 获取队列中有效元素个数
int QueueSize(Queue* q)
{
	assert(q);//q不能为空指针
	//assert(!QueueEmpty(q));//这个队列要不为空
	return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q)
{
	assert(q);
	return q->head == NULL && q->tail == NULL;
}
// 销毁队列
void QueueDestroy(Queue* q)
{
	QNode* cur = q->head;
	while (cur)
	{
		Queue* del = q->head;
		cur = cur->next;
		free(del);
	}
	q->head = q->tail = NULL;
	q->size = 0;
}

test.c

#define  _CRT_SECURE_NO_WARNINGS 1
#include "Queue.h"
void TestQueue()
{
	//Queue q1;
	//Queue q2;
	//QueueInit(&q1);
	//QueueInit(&q2);


	//QueueDestroy(&q1);
	//QueueDestroy(&q2);

	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);

	printf("%d ", QueueFront(&q));
	QueuePop(&q);

	QueuePush(&q, 3);
	QueuePush(&q, 4);

	printf("%d\n", QueueSize(&q));
	printf("%d\n", QueueEmpty(&q));
	printf("%d\n", QueueFront(&q));
	printf("%d\n", QueueBack(&q));

	while (!QueueEmpty(&q))
	{
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}
	printf("\n");

	printf("%d\n", QueueSize(&q));
	printf("%d\n", QueueEmpty(&q));
	//printf("%d\n", QueueFront(&q));
	//printf("%d\n", QueueBack(&q));

	QueueDestroy(&q);
}

int main()
{
	TestQueue();
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值