C语言数据结构-栈和队列


1 栈的表示与实践

1.1 栈的概念及结构

栈:一种特殊的线性表,其只允许在固定一段进行插入和删除元素操作。
进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。
栈中的数据元素遵循后进先出LIFO(Last in First out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。
在这里插入图片描述

1.2 定义数据结构

//1 定义栈的数据结构类型
typedef int StackDataType;
//动态增长的栈
typedef struct Stack
{
    
    
	StackDataType* a;
	int top;
	int capacity;

}Stack;


//静态栈一般不用,我们常常使用动态增长的栈
//typedef struct Stack
//{
    
    
//	STDataType a[50];
//	int top;
//}Stack;

1.3 初始化与销毁

ps->top = 0; 和ps->top = -1;说实话我也说不清楚,要根据画图思考,根据调试得结果
在这里插入图片描述

void StackInit(Stack* ps)
{
    
    
	assert(ps);
	//刚刚开始给4个数据结构大小
	ps->a = (StackDataType*)malloc(sizeof(StackDataType) * 4);
	if (ps->a == NULL)
	{
    
    
		printf("malloc fail\n");
		exit(-1);
	}
	ps->capacity = 4;
	ps->top = 0;	//top指向栈顶元素的后一个
	//ps->top = -1;   //top指向栈顶元素

}


void StackDestory(Stack* ps)
{
    
    
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}

1.4 入栈

接下来跟我们前面学的顺序表,链表十分类似,也比较容易理解

//检查扩容
void StackCheckCapacity(Stack* ps)
{
    
    
	assert(ps);
	if (ps->top == ps->capacity)
	{
    
    
		StackDataType* tmp = (StackDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(StackDataType));
		if (tmp == NULL)
		{
    
    
			printf("realloc fail\n");
			return;
		}
		ps->a = tmp;
		ps->capacity *= 2;   //初始化函数中,capacity大小为4
	}
}

void StackPush(Stack* ps, StackDataType x)
{
    
    
	assert(ps);
	//检查扩容
	StackCheckCapacity(ps);

	//ps->a[ps->top] = x;
	//ps->top++;
	//上面两个代码简写成一下一行
	ps->a[ps->top++] = x;
}

1.5 出栈

void StackPop(Stack* ps)
{
    
    
	assert(ps);
	//当栈顶没有元素再删除就产生越界
	assert(ps->top > 0);

	ps->top--;
	//ps->a[ps->top - 1] = 0;
}

1.6 栈顶的数据

StackDataType StackTop(Stack* ps)
{
    
    
	assert(ps);
	assert(ps->top > 0);
	//取出栈顶元素
	return ps->a[ps->top - 1];
}

1.7 栈的个数

int StackSize(Stack* ps)
{
    
    
	assert(ps);
	//tope位于栈最后一个元素的下一个,同时是前面的数据个数
	return ps->top;
}

1.8 栈是否是空

布尔类型检查空间是否是空挺合适的

bool StackIfEmpty(Stack* ps)
{
    
    
	assert(ps);
	//如果是top是0,真,栈空
	return ps->top==0;
}

1.9 打印栈

简单封装一下

void StackPrint(Stack* ps)
{
    
    

	while (!StackIfEmpty(ps))
	{
    
    
		printf("%d ", StackTop(ps));
		StackPop(ps);
	}
	printf("\n");
}

2 队列的表示与实现

2.1 队列的概念与结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先
进先出FIFO(First In First Out) 。 即队尾入,队头出。
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
front 队头, rear队尾 在百度百科找的图
在这里插入图片描述

2.2 队列的数据结构定义

typedef int QueueDataType;
typedef struct QueueNode
{
    
    
	QueueDataType data;
	struct QueueNode* next;
}QNode;

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

2.3 队列的初始化与销毁

销毁队列记得存储 cur->next
销毁队列记得存储 cur->next
销毁队列记得存储 cur->next

void QueueInit(Queue* pq)
{
    
    
	assert(pq);
	pq->head = pq->tail = NULL;
}

void QueueDestory(Queue* pq)
{
    
    
	assert(pq);

	QNode* cur = pq->head;
	while (cur)
	{
    
    
		QNode* NEXT = cur->next;
		free(cur);
		cur = NEXT;
	}
	pq->head = pq->tail = NULL;
}

2.4 入队

常常忘记队列为空时的情况了

//队尾插入数据
void QueuePush(Queue* pq, QueueDataType x)
{
    
    
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
    
    
		printf("malloc fail\n");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	
	//插入的第一个节点
	if (pq->tail == NULL)
	{
    
    
		pq->head = pq->tail = newnode;
	}
	//已经有一个节点
	else
	{
    
    
		pq->tail->next = newnode;
		//pq->tail = newnode;
		pq->tail = pq->tail->next;
	}
}

2.5 出队

//队头取出数据
void QueuePop(Queue* pq)
{
    
    
	assert(pq);
	assert(pq->head);
	if (pq->head->next == NULL)
	{
    
    
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
    
    
		QNode* NEXT = pq->head->next;
		free(pq->head);
		pq->head = NEXT;
	}
}

2.6 取队头数据

QueueDataType QueueFront(Queue* pq)
{
    
    
	assert(pq);
	assert(pq->head);

	return pq->head->data;
}

2.7 取队尾数据

QueueDataType QueueBack(Queue* pq)
{
    
    
	assert(pq);
	assert(pq->head);
	return pq->tail->data;
}

2.8 队的个数

int QueueSize(Queue* pq)
{
    
    
	assert(pq);
	int size = 0;
	QNode* cur = pq->head;
	while (cur)
	{
    
    
		size++;
		cur=cur->next;
	}
	return size;
}

2.9 判断队是否是空

bool QueueIfEmpty(Queue* pq)
{
    
    
	assert(pq);
	return pq->head==NULL;
}

2.10 打印出队列

void QueuePrint(Queue* pq)
{
    
    
	while (!QueueIfEmpty(pq))
	{
    
    
		printf("%d ", QueueFront(pq));
		QueuePop(pq);
	}
	printf("\n");
}

3 栈和队列完整代码

3.1 Stack.h

#pragma once

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

//1 定义栈的数据结构类型
typedef int StackDataType;

//静态栈一般不用,我们常常使用动态增长的栈
//typedef struct Stack
//{
    
    
//	STDataType a[50];
//	int top;
//}Stack;

//动态增长的栈
typedef struct Stack
{
    
    
	StackDataType* a;
	int top;
	int capacity;

}Stack;

//2 初始化与销毁
void StackInit(Stack* ps);
void StackDestory(Stack* ps);

//3 入栈
void StackPush(Stack* ps, StackDataType x);

//4 出栈
void StackPop(Stack* ps);

//5 返回栈顶的数据
StackDataType StackTop(Stack* ps);

//6 栈的个数
int StackSize(Stack* ps);

//7 栈是否是空
bool StackIfEmpty(Stack* ps);

//8 打印栈
void StackPrint(Stack* ps);

3.2 Stack.c

#include "Stack.h"
void StackInit(Stack* ps)
{
    
    
	assert(ps);
	//刚刚开始给4个数据结构大小
	ps->a = (StackDataType*)malloc(sizeof(StackDataType) * 4);
	if (ps->a == NULL)
	{
    
    
		printf("malloc fail\n");
		exit(-1);
	}
	ps->capacity = 4;
	ps->top = 0;	//top指向栈顶元素的后一个
	//ps->top = -1;   //top指向栈顶元素

}

void StackDestory(Stack* ps)
{
    
    
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}

//检查扩容
void StackCheckCapacity(Stack* ps)
{
    
    
	assert(ps);
	if (ps->top == ps->capacity)
	{
    
    
		StackDataType* tmp = (StackDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(StackDataType));
		if (tmp == NULL)
		{
    
    
			printf("realloc fail\n");
			return;
		}
		ps->a = tmp;
		ps->capacity *= 2;   //初始化函数中,capacity大小为4
	}
}

void StackPush(Stack* ps, StackDataType x)
{
    
    
	assert(ps);
	//检查扩容
	StackCheckCapacity(ps);

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

void StackPop(Stack* ps)
{
    
    
	assert(ps);
	//当栈顶没有元素再删除就产生越界
	assert(ps->top > 0);

	ps->top--;
	//ps->a[ps->top - 1] = 0;
}

StackDataType StackTop(Stack* ps)
{
    
    
	assert(ps);
	assert(ps->top > 0);
	//取出栈顶元素
	return ps->a[ps->top - 1];
}

int StackSize(Stack* ps)
{
    
    
	assert(ps);
	//tope位于栈最后一个元素的下一个,同时是前面的数据个数
	return ps->top;
}

bool StackIfEmpty(Stack* ps)
{
    
    
	assert(ps);
	//如果是top是0,真,栈空
	return ps->top==0;
}

void StackPrint(Stack* ps)
{
    
    

	while (!StackIfEmpty(ps))
	{
    
    
		printf("%d ", StackTop(ps));
		StackPop(ps);
	}
	printf("\n");
}

3.3 Queue.h

#pragma once

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
//队尾入,队头出

//定义队列数据结构
typedef int QueueDataType;
typedef struct QueueNode
{
    
    
	QueueDataType data;
	struct QueueNode* next;
}QNode;

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

//队列的初始化与销毁
void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);

//插入与取出
void QueuePush(Queue* pq, QueueDataType x);
void QueuePop(Queue* pq);

//取队头数据
QueueDataType QueueFront(Queue* pq);
//取队尾数据
QueueDataType QueueBack(Queue* pq);

//队的个数
int  QueueSize(Queue* pq);
//判断队是否是空
bool QueueIfEmpty(Queue* pq);

//打印出队列
void QueuePrint(Queue* pq);

3.4 Queue.c

#include "Queue.h"

void QueueInit(Queue* pq)
{
    
    
	assert(pq);
	pq->head = pq->tail = NULL;
}

void QueueDestory(Queue* pq)
{
    
    
	assert(pq);

	QNode* cur = pq->head;
	while (cur)
	{
    
    
		QNode* NEXT = cur->next;
		free(cur);
		cur = NEXT;
	}
	pq->head = pq->tail = NULL;
}

//队尾插入数据
void QueuePush(Queue* pq, QueueDataType x)
{
    
    
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
    
    
		printf("malloc fail\n");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	
	//插入的第一个节点
	if (pq->tail == NULL)
	{
    
    
		pq->head = pq->tail = newnode;
	}
	//已经有一个节点
	else
	{
    
    
		pq->tail->next = newnode;
		//pq->tail = newnode;
		pq->tail = pq->tail->next;
	}
}


//队头取出数据
void QueuePop(Queue* pq)
{
    
    
	assert(pq);
	assert(pq->head);
	if (pq->head->next == NULL)
	{
    
    
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
    
    
		QNode* NEXT = pq->head->next;
		free(pq->head);
		pq->head = NEXT;
	}
}

QueueDataType QueueFront(Queue* pq)
{
    
    
	assert(pq);
	assert(pq->head);

	return pq->head->data;
}

QueueDataType QueueBack(Queue* pq)
{
    
    
	assert(pq);
	assert(pq->head);
	return pq->tail->data;
}

int QueueSize(Queue* pq)
{
    
    
	assert(pq);
	int size = 0;
	QNode* cur = pq->head;
	while (cur)
	{
    
    
		size++;
		cur=cur->next;
	}
	return size;
}

bool QueueIfEmpty(Queue* pq)
{
    
    
	assert(pq);
	return pq->head==NULL;
}

void QueuePrint(Queue* pq)
{
    
    
	while (!QueueIfEmpty(pq))
	{
    
    
		printf("%d ", QueueFront(pq));
		QueuePop(pq);
	}
	printf("\n");
}

3.5 test.c

#include"Stack.h"
#include"Queue.h"
void test_stack()
{
    
    
	Stack stack;
	StackInit(&stack);


	StackPush(&stack, 1);
	StackPush(&stack, 2);
	StackPush(&stack, 3);
	StackPush(&stack, 4);
	StackPush(&stack, 5);
	printf("%d ", StackTop(&stack));
	
	StackPop(&stack);
	printf("%d ", StackTop(&stack));

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

	StackPush(&stack, 11);
	StackPush(&stack, 12);
	printf("\n");
	StackPrint(&stack);

	StackDestory(&stack);

}

void test_Queen()
{
    
    
	Queue queue;
	QueueInit(&queue);
	QueuePush(&queue,1);
	QueuePush(&queue,2);
	QueuePush(&queue,3);
	QueuePush(&queue,4);
	QueuePush(&queue,5);

	printf("%d ", QueueSize(&queue));

	//printf("\n");
	//printf("%d ", QueueFront(&queue));
	//printf("%d ", QueueBack(&queue));

	//printf("\n");
	//QueuePop(&queue);
	//QueuePop(&queue);
	//printf("%d ", QueueFront(&queue));
	//printf("%d ", QueueBack(&queue));


	printf("\n");
	//QueuePrint(&queue);
	while (!QueueIfEmpty(&queue))
	{
    
    
		printf("%d ", QueueFront(&queue));
		QueuePop(&queue);
	}
	printf("\n");

	QueueDestory(&queue);
}

int main()
{
    
    
	//test_stack();
	test_Queen();
	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_73678713/article/details/134939662