学习笔记—数据结构—栈和队列

目录

一、栈的基本概念

1、栈的定义

2、栈的常见的基础操作

3、栈的实现

(1)结构体

(2)初始化

(3)进栈(插入操作)

(4)出栈(删除操作)

(5)计算栈内元素个数

(6)判断栈内是否为空

(7)读取栈顶元素

(8)销毁

(9)增容

队列

一、队列的基本概念

1、队列的定义

2、队列的常见的基础操作

3、队列的实现

(1)结构体

(2)初始化

(3)入队(插入操作)

(4)判断队列是否为空

(5)出队(删除操作)

(6)读取队头数据

(7)读取队尾数据

(8)计算队内元素个数

(9)销毁

总结

头文件Stack.h

Stack.c

测试文件test.c

队列

头文件Queue.h

Queue.c

测试文件test.c


前言:

前面介绍了顺序表、单链表(单向非循环链表)、双链表(双向循环链表),基本上已经结束了链表的讲解,今天谈一下栈和队列。可以简单的说是前面学习的一特殊化实现,但是总体是相似的。

一、栈的基本概念

1、栈的定义

:⼀种特殊的线性表,只允许在固定的⼀端进行插入和删除元素操作。进行数据插⼊和删除操作 的⼀端称为栈顶,另⼀端称为栈底。栈中的数据元素遵守后进先出LIFO(LastInFirstOut)的原则。


栈顶:能进行进栈(插入)和出栈(删除)操作。

栈底:固定的,不能进行任何操作。

空栈:没有任何元素,栈顶=栈底。

2、栈的常见的基础操作

● STInit(&st):初始化一个空栈st。
● STEmpty(&st):判断一个栈是否为空,若栈为空则返回true,否则返回false。
● STPush(&st,x):进栈(栈的插入操作),若栈st未满,则将x加入使之成为新栈顶。
● STPop(&st):出栈(栈的删除操作),若栈st非空,则弹出栈顶元素,并用x返回。

● STCheckCapacity(&st):增容,栈顶等于栈的空间大小时,空间增大一倍。

● STSize(&st):大小,计算队列元素个数,返回capacity。
● GetTop(&st):读栈顶元素,若栈st非空,则用top返回栈顶元素。
● STDestroy(st):栈销毁,并释放st占用的存储空间。

3、栈的实现

(1)结构体
typedef int STDataType;

typedef struct stack
{
	STDataType* a;
	int top;         //栈顶
	int capacity;    //栈的空间大小
}ST;
(2)初始化
void STInit(ST* ps)
{
	assert(ps);
	ps->a = (STDataType*)malloc(sizeof(STDataType)*4);
	if (ps->a == NULL)
	{
		perror("malloc fail");
		return;
	}
	
	ps->capacity = 4;
	ps->top = 0;
}
(3)进栈(插入操作)

void STpush(ST* ps,STDataType x)
{
	assert(ps);

	ps->a[ps->top] = x;
	ps->top++;
}
(4)出栈(删除操作)

void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));

	ps->top--;
}
(5)计算栈内元素个数
int STSize(ST* ps)
{
	assert(ps);

	return ps->top;
}
(6)判断栈内是否为空
bool STEmpty(ST* ps)
{
	assert(ps);

	return ps->top == 0;
}
(7)读取栈顶元素
STDataType STTop(ST* ps)
{
	assert(ps);
    assert(!StackEmpty(ps))

	return ps->a[ps->top-1];
}
(8)销毁
void STDestroy(ST* ps)
{
	assert(ps);

	free(ps->a);
	ps->a = NULL;
	ps->capacity = 0;
	ps->top = 0;
}
(9)增容
//检查容量
void CheckCapacity(ST*ps)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		ST* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * (ps->capacity) * 2);
		if (tmp == NULL)
		{
			perror("malloc fail");
			return;
		}
		ps->capacity *= 2;
		ps->a = tmp;
	}
}

队列

一、队列的基本概念

1、队列的定义

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

  • 队头:进行删除的一端,又称队首。
    队尾:进行插入的一端。
    空队列:不包含任何元素的空表。

2、队列的常见的基础操作

● QueueInit(&s):初始化队列,构造一个空队列ps。
● QueueEmpty(s):判队列空,若队列ps为空返回true,否则返回false。
● QueuePush(&s, x):入队,若队列ps未满,将x加入,使之成为新的队尾。
● QueuePop(&s):出队,若队列ps非空,删除队头元素,并用x返回。
● QueueFront(s, &x):读队头元素,若队列ps非空,则将队头元素赋值给x。

● QueueBack:读队尾元素,若队列ps非空,则将队头元素赋值给x。

● QueueDestroy(&s):队列销毁,并释放ps占用的存储空间。

3、队列的实现

(1)结构体
typedef int QDataType;
typedef struct QueueNode
{
	QDataType data;
	struct QueueNode* next;
}QueueNode;

typedef struct Queue
{
	QueueNode* phead;//队头
	QueueNode* ptail;//队尾

	int size;        //队内元素个数
}Queue;
(2)初始化
void QueueInit(Queue* ps)
{
	assert(ps);

	ps->phead = ps->ptail = NULL;

	ps->size = 0;

}
(3)入队(插入操作)

void QueuePush(Queue* ps, QDataType x)
{
	assert(ps);

	//创建一个节点newnode
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;
	//当队列为空时
	if (ps->phead == NULL)
	{
		ps->phead = ps->ptail = newnode;
	}
	//队列不为空时
	else
	{
		ps->ptail->next = newnode;
		ps->ptail = newnode;
	}

	ps->size++;

}
(4)判断队列是否为空
bool QueueEmpty(Queue* ps)
{
	assert(ps);
	return ps->phead = NULL && ps->ptail == NULL;
}
(5)出队(删除操作)

void QueuePop(Queue* ps)
{
	assert(ps);
	assert(! QueueEmpty(ps));

	//只有一个节点时,避免ptail成为野指针
	if (ps->ptail == ps->phead)
	{
		free(ps->phead);
		ps->phead = ps->ptail = NULL;
	}
	else
	{
		//删除头元素
		QueueNode* next = ps->phead->next;
		free(ps->phead);
		ps->phead = next;
	}
	ps->size--;
}
(6)读取队头数据
QDataType QueueFront(Queue* ps)
{
	assert(ps);
	assert(!QueueEmpty(ps));
	return ps->phead->data;
}
(7)读取队尾数据
QDataType QueueBack(Queue* ps)
{
	assert(ps);
	assert(!QueueEmpty(ps));
	return ps->ptail->data;
}
(8)计算队内元素个数
int Queuesize(Queue* ps)
{
	assert(ps);
	return ps->size;
}
(9)销毁
void QueueDestroy(Queue* ps)
{
	assert(ps);
	assert(!QueueEmpty(ps));
	QueueNode* pcur = ps->phead;
	while (pcur)
	{
		QueueNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	ps->phead = ps->ptail = NULL;
	ps->size = 0;
}

总结

头文件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 STInit(ST* ps);
//压栈
void STpush(ST* ps, STDataType x);
//删除
void STPop(ST* ps);
//大小
int STSize(ST* ps);
//判空
bool STEmpty(ST* ps);
//出栈
STDataType STTop(ST* ps);
//检查容量
void CheckCapacity(ST* ps);
//销毁
void STDestroy(ST* ps);

Stack.c

#define _CRT_SECURE_NO_WARNINGS


#include "stack.h"


//初始化
void STInit(ST* ps)
{
	assert(ps);
	ps->a = (STDataType*)malloc(sizeof(STDataType*)*4);
	if (ps->a == NULL)
	{
		perror("malloc fail");
		return;
	}
	
	ps->capacity = 4;
	ps->top = 0;
}
//销毁
void STDestroy(ST* ps)
{
	assert(ps);

	free(ps->a);
	ps->a = NULL;
	ps->capacity = 0;
	ps->top = 0;
}

//检查容量
void CheckCapacity(ST*ps)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		ST* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * (ps->capacity) * 2);
		if (tmp == NULL)
		{
			perror("malloc fail");
			return;
		}
		ps->capacity *= 2;
		ps->a = tmp;
	}
}

//压栈
void STpush(ST* ps,STDataType x)
{
	assert(ps);

	ps->a[ps->top] = x;
	ps->top++;
}

//删除
void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));

	ps->top--;
}

//判空
bool STEmpty(ST* ps)
{
	assert(ps);

	return ps->top == 0;
}

//出栈
STDataType STTop(ST* ps)
{
	assert(ps);

	return ps->a[ps->top-1];
}

//大小
int STSize(ST* ps)
{
	assert(ps);

	return ps->top;
}

测试文件test.c

#define _CRT_SECURE_NO_WARNINGS


#include "stack.h"

void teststack()
{
	ST st;
	STInit(&st);

	STpush(&st, 1);
	STpush(&st, 2);
	STpush(&st, 3);
	STpush(&st, 4);
	STpush(&st, 5);

	printf("%d", STSize(&st));
	printf("\n");

	while (!STEmpty(&st))
	{
		printf("%d ", STTop(&st));
		STPop(&st);
	}
	printf("\n");
	printf("%d", STSize(&st));

	STDestroy(&st);

}



int main()
{
	teststack();

	return 0;
}

队列

头文件Queue.h

#pragma once

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

//定义队列的结构
typedef int QDataType;
typedef struct QueueNode
{
	QDataType data;
	struct QueueNode* next;
}QueueNode;

typedef struct Queue
{
	QueueNode* phead;
	QueueNode* ptail;

	int size;
}Queue;

//链表的实现

//初始化
void QueueInit(Queue* ps);
//入栈
void QueuePush(Queue* ps, QDataType x);
//队列判空
bool QueueEmpty(Queue* ps);
//出栈
void QueuePop(Queue* ps);
//取队头数据
QDataType QueueFront(Queue* ps);
//取队尾数据
QDataType QueueBack(Queue* ps);
//队列有效元素
int Queuesize(Queue* ps);
//销毁队列
void QueueDestroy(Queue* ps);

Queue.c

#include"Queue.h"

//初始化
void QueueInit(Queue* ps)
{
	assert(ps);

	ps->phead = ps->ptail = NULL;

	ps->size = 0;

}

//入栈
void QueuePush(Queue* ps, QDataType x)
{
	assert(ps);

	//创建一个节点newnode
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;
	//当队列为空时
	if (ps->phead == NULL)
	{
		ps->phead = ps->ptail = newnode;
	}
	//队列不为空时
	else
	{
		ps->ptail->next = newnode;
		ps->ptail = newnode;
	}

	ps->size++;

}

//队列判空
bool QueueEmpty(Queue* ps)
{
	assert(ps);
	return ps->phead = NULL && ps->ptail == NULL;
}

//出栈
void QueuePop(Queue* ps)
{
	assert(ps);
	assert(! QueueEmpty(ps));

	//只有一个节点时,避免ptail成为野指针
	if (ps->ptail == ps->phead)
	{
		free(ps->phead);
		ps->phead = ps->ptail = NULL;
	}
	else
	{
		//删除头元素
		QueueNode* next = ps->phead->next;
		free(ps->phead);
		ps->phead = next;
	}
	ps->size--;
}

//取队头数据
QDataType QueueFront(Queue* ps)
{
	assert(ps);
	assert(!QueueEmpty(ps));
	return ps->phead->data;
}

//取队尾数据
QDataType QueueBack(Queue* ps)
{
	assert(ps);
	assert(!QueueEmpty(ps));
	return ps->ptail->data;
}

//队列有效元素
int Queuesize(Queue* ps)
{
	assert(ps);
	return ps->size;
}

//销毁队列
void QueueDestroy(Queue* ps)
{
	assert(ps);
	assert(!QueueEmpty(ps));
	QueueNode* pcur = ps->phead;
	while (pcur)
	{
		QueueNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	ps->phead = ps->ptail = NULL;
	ps->size = 0;
}

测试文件test.c

#define _CRT_SECURE_NO_WARNINGS

#include "queue.h"



void testQueue()
{
	Queue s;
	QueueInit(&s);

	QueuePush(&s, 1);
	QueuePush(&s, 2);
	QueuePush(&s, 3);
	QueuePush(&s, 4);



	//printf("%d ", QueueTop(&s));
	//QueuePop(&s);
	//printf("%d ", QueueTop(&s));
	//QueuePop(&s);	
	//printf("%d ", QueueTop(&s));
	//QueuePop(&s);	
	//printf("%d ", QueueTop(&s));
	//QueuePop(&s);
	//printf("\n");

	while (!(QueueEmpty(&s)))
	{
		printf("%d ", QueueTop(&s));
		QueuePop(&s);
	}


	QueueDestroy(&s);

}

int main()
{
	testQueue();


	return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值