<栈和队列及模拟实现>——《Data Structure in C Train》

目录

详细实现链接:

<栈(动态版)>《数据结构(C语言版)》

<队列(链式)>《数据结构(C语言版)》

1.分析实现功能、感受栈和队列的实现结构:

1.1栈的实现结构方式:​

1.2 队列的实现方式:

2.完整源码:

2.1栈的模拟实现: 

Stack.h:

Stack.c:

Test.c:

2.2 队列的模拟实现:

Queue.h:

Queue.c:

Test.c:

 3.判断括号匹配程序:

后记:●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!

                                                                       ——By 作者:新晓·故知


详细实现链接:

<栈(动态版)>《数据结构(C语言版)》

<队列(链式)>《数据结构(C语言版)》


1.分析实现功能、感受栈和队列的实现结构:

1.1栈的实现结构方式:

数组实现栈的结构:

相当于顺序表的尾插、尾删,用尾作栈顶,非常合适!从CPU预加载命中角度分析,数组实现的性能更好一些!

缺点:空间不够时需要增容。

单向链表实现栈的结构:

用头结点作栈底,这样使得入栈和出栈效率都是O(1)。

双向链表实现栈的结构:

用尾作栈顶。

1.2 队列的实现方式:

数组实现队列的结构:

不适合,队头出数据需要挪动数据

单链表实现队列的结构:

无需使用带头结点的单链表即可完成,带头结点是为了减少二级指针的使用。

tail是移动的,方便尾部操作直接找到。head方便头部操作直接找到。

 

数据结构的设计比较灵活,正所谓:“树挪死,人挪活”。在学习中,不要一味地“守死”,而要学会“变活。”

2.完整源码:

2.1栈的模拟实现: 

Stack.h:

#pragma once

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

typedef char STDataType;

typedef struct Stack
{
	STDataType* a;   //通过数组实现栈的结构
	int top;
	int capacity;
}ST;
//初始化
void StackInit(ST* ps);
//释放内存、销毁空间
void StackDestory(ST* ps);
// 入栈
void StackPush(ST* ps, STDataType x);
// 出栈
void StackPop(ST* ps);
//取栈顶数据
STDataType StackTop(ST* ps);
//栈的大小
int StackSize(ST* ps);
//判空
bool StackEmpty(ST* ps);

Stack.c:

#include"Stack.h"
//初始化
void StackInit(ST* ps)
{
	assert(ps);

	ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
	if (ps->a == NULL)
	{
		printf("malloc fail!\n");
		exit(-1);
	}

	ps->capacity = 4;
	ps->top = 0; //这使得top最终指向的是栈顶的后一个位置。若top=-1,则最终指向的是栈顶。
}
//释放内存、销毁空间
void StackDestory(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->top == ps->capacity)
	{
		STDataType* tmp = (STDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(STDataType));
		if (tmp == NULL)
		{
			printf("realloc fail!\n");
			exit(-1);
		}
		else
		{
			ps->a = tmp;
			ps->capacity *= 2;
		}
	}

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

// 出栈
void StackPop(ST* ps)
{
	assert(ps);
	// 栈空了,再调用Pop,就会直接中止程序报错
	assert(ps->top > 0);

	//ps->a[ps->top - 1] = 0; //置为0只考虑了int型等,若为char、double等就不适用了。
	ps->top--;
}
//取栈顶数据
STDataType StackTop(ST* ps)
{
	assert(ps);
	// 栈空了,再调用Top,就会直接中止程序报错
	assert(ps->top > 0);

	return ps->a[ps->top - 1];
}
//求栈大小
int StackSize(ST* ps)
{
	assert(ps);

	return ps->top;
}
//判空
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

//判断括号是否匹配算法
bool isValid(char* s) {
	ST st;
	StackInit(&st);
	while (*s != '\0')
	{
		switch (*s)
		{
		case '{':
		case '[':
		case '(':
		{
			StackPush(&st, *s);
			++s;
			break;
		}
		case '}':
		case ']':
		case ')':
		{
			if (StackEmpty(&st))
			{
				StackDestory(&st);
				return false;
			}

			char top = StackTop(&st);
			StackPop(&st);

			// 不匹配
			if ((*s == '}' && top != '{')
				|| (*s == ']' && top != '[')
				|| (*s == ')' && top != '('))
			{
				StackDestory(&st);
				return false;
			}
			else // 匹配
			{
				++s;
			}
			break;
		}
		default:
			break;
		}
	}
	bool ret = StackEmpty(&st);
	StackDestory(&st);
	return ret;
}

Test.c:

#include"Stack.h"

int main()
{
	ST st;
	StackInit(&st);
	StackPush(&st, 9);
	StackPush(&st, 5);
	StackPush(&st, 2);
	StackPush(&st, 7);

	printf("%d \n", StackEmpty(&st));
	printf("%d \n", StackSize(&st));
	while (!StackEmpty(&st))
	{
	
		printf("%d ", StackTop(&st));
		StackPop(&st);
	}
	printf("\n");
	
	StackDestory(&st);
	return 0;
}

2.2 队列的模拟实现:

Queue.h:

#pragma once

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

typedef int QDataType;

typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QNode;

typedef struct Queue
{
	QNode* head;
	QNode* tail;
}Queue;
//初始化
void QueueInit(Queue* pq);
//销毁
void QueueDestory(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"

//初始化
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, QDataType 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;
	}
}
// 队头出
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->head);

	// 1、一个
	// 2、多个
	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;
	}
}
//取队头元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->head);

	return pq->head->data;
}
//取队尾元素
QDataType 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 QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->head == NULL;
}

Test.c:

#include"Queue.h"

void TestQueue()
{
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	printf("%d ", QueueFront(&q));
	QueuePop(&q);
	printf("%d ", QueueFront(&q));
	QueuePop(&q);

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

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

	QueueDestory(&q);
}

int main()
{
	
	TestQueue();

	return 0;
}

 3.判断括号匹配程序:

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

///
//声明
typedef char STDataType;

typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

//
//定义
//初始化
void StackInit(ST* ps)
{
	assert(ps);

	ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
	if (ps->a == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}

	ps->capacity = 4;
	ps->top = 0;
}
//销毁
void StackDestory(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->top == ps->capacity)
	{
		STDataType* tmp = (STDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(STDataType));
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		else
		{
			ps->a = tmp;
			ps->capacity *= 2;
		}
	}

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

// 出栈
void StackPop(ST* ps)
{
	assert(ps);
	// 栈空了,调用Pop,直接中止程序报错
	assert(ps->top > 0);

	//ps->a[ps->top - 1] = 0;
	ps->top--;
}
//去栈顶元素
STDataType StackTop(ST* ps)
{
	assert(ps);
	// 栈空了,调用Top,直接中止程序报错
	assert(ps->top > 0);

	return ps->a[ps->top - 1];
}
//求栈的的大小
int StackSize(ST* ps)
{
	assert(ps);

	return ps->top;
}
//判空
bool StackEmpty(ST* ps)
{
	assert(ps);

	return ps->top == 0;
}
//判断括号是否匹配
bool isValid(char* s) {
	ST st;
	StackInit(&st);
	while (*s != '\0')
	{
		switch (*s)
		{
		case '{':
		case '[':
		case '(':
		{
			StackPush(&st, *s);
			++s;
			break;
		}
		case '}':
		case ']':
		case ')':
		{
			if (StackEmpty(&st))
			{
				StackDestory(&st);
				return false;
			}

			char top = StackTop(&st);
			StackPop(&st);

			// 不匹配
			if ((*s == '}' && top != '{')
				|| (*s == ']' && top != '[')
				|| (*s == ')' && top != '('))
			{
				StackDestory(&st);
				return false;
			}
			else // 匹配
			{
				++s;
			}
			break;
		}
		default:
			break;
		}
	}

	bool ret = StackEmpty(&st);
	StackDestory(&st);
	return ret;
}

int main()
{
	//int ret = isValid("[[[");
	//int ret = isValid("[][");
	int ret = isValid("[]");
	if (ret == 0)
	{
		printf("不匹配!\n" );
	}
	else
	{
		printf("匹配!\n");
	}
	return 0;
}

后记:
●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!

                                                                       ——By 作者:新晓·故知

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值