栈 和 队列

文章详细介绍了栈和队列的基本概念、结构以及使用数组和链表的实现方式。提供了C语言的代码实现,包括栈的动态扩容、入栈、出栈等操作,以及队列的初始化、入队、出队等操作。此外,文章还展示了如何使用栈解决括号匹配问题,以及如何用两个队列模拟栈的行为。最后,提到了循环队列的概念及其在数组上的实现。
摘要由CSDN通过智能技术生成

栈的表示和实现

栈的概念及结构

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

栈的实现

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

栈的代码实现

Stack.h

#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#include <stdlib.h>
typedef int STDataType;

/// 静态栈
//#define MAX 10000
//struct Stack
//{
//	STDataType a[MAX];
//	int top;
//};

/// 动态栈
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;
}

// 销毁栈
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;
}

text.c

#include "Stack.h"

void TestStack()
{
	ST st;
	StackInit(&st);
	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);

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

	StackPush(&st, 4);
	StackPush(&st, 5);

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

	StackDestory(&st);
}

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

队列的表示和实现

队列的概念及结构​

在这里插入图片描述

队列的实现

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

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);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
bool QueueEmpty(Queue* pq);


Queue.c

// 初始化队列
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;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->head == NULL;
}

text.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;
}

栈和队列OJ题

括号匹配问题

思路:

1. 左括号,入栈。

2 .右括号,出栈顶的左括号跟右括号判断是否匹配,如果匹配,继续,不匹配,终止。

3.最终判断栈是否为空
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 ps;
    StackInit(&ps);
    while(*s != '\0')
    {
        switch(*s)
        {
            case '(':
            case '{':
            case '[':
            {
                StackPush(&ps,*s);
                s++;
                break;
            }
            case ')':
            case '}':
            case ']':
            {
                if(StackEmpty(&ps)) //当输入用例为 "]"
                {
                    StackDestory(&ps);
                    return false;
                }
                STDataType tmp = StackTop(&ps);
                StackPop(&ps);
                if(tmp == '(' && *s != ')'
                || tmp == '{' && *s != '}'
                || tmp == '[' && *s != ']')
                {
                    StackDestory(&ps);
                    return false;
                }
                else
                {
                    s++;
                }
            }
            break;
        }
    }
    bool ret = StackEmpty(&ps); //判断栈是否为空
    StackDestory(&ps);
    return ret;
}

用队列实现栈

栈是先进后出,队列是先进先出,我们要使用两个队列实现栈。

思路:

1. 入数据,往不为空的队列入。

2. 出数据,把不为空的队列数据导入到为空的队列,直到只剩下一个。

函数内部的static变量,关键在于生命周期持久,他的值不会随着函数调用的结束而消失,
下一次调用时,static变量的值,还保留着上次调用后的内容。 
typedef int QDataType;
// 链式结构:表示队列
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QNode;
 
// 队列的结构
typedef struct Queue
{
	QNode* head;
	QNode* tail;
}Queue;

// 初始化队列
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;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->head == NULL;
}

typedef struct {
    // 创建两个队列
    Queue q1;
    Queue q2;
} MyStack;


MyStack* myStackCreate() {
    /*这种创建方法错误,局部变量会随着该函数的结束被销毁*/
    /*如果使用静态变量,每次调用此函数,static变量还保留上次调用后的内容*/
    // MyStack ps;
    // return &ps;

    MyStack* ps = (MyStack*)malloc(sizeof(MyStack));
    if(ps == NULL)
    {
        printf("malloc fail\n");
    }
    QueueInit(&(ps->q1));
    QueueInit(&(ps->q2));
    return ps;
}

void myStackPush(MyStack* obj, int x) {
    // 往非空的插入数据
    if(!QueueEmpty(&(obj->q1)))
    {
        QueuePush(&(obj->q1),x);
    }
    else
    {
        QueuePush(&(obj->q2),x);
    }
}

int myStackPop(MyStack* obj) {
    // 将非空的有N个数的队列移入N-1个数到空的队列,然后删除最后每移入的最后那个数
    Queue*emptyQ = &(obj->q1); // 先假设空队列为 q1 非空列表为q2
    Queue*noneEmptyQ = &(obj->q2);
    if(!QueueEmpty(&(obj->q1))) // 当q1非空进来, 假设错误则,空队列为 q2 非空列表为q1
    {
        emptyQ = &(obj->q2);
        noneEmptyQ = &(obj->q1);
    }
    // 导入数据
    while(QueueSize(noneEmptyQ) > 1)
    {
        QueuePush(emptyQ, QueueFront(noneEmptyQ));
        QueuePop(noneEmptyQ);
    }
    int top = QueueFront(noneEmptyQ);
    QueuePop(noneEmptyQ);
    return top;
}

int myStackTop(MyStack* obj) {
    if(!QueueEmpty(&(obj->q1)))
    {
        return QueueBack(&(obj->q1));
    }
    else
    {
        return QueueBack(&(obj->q2));
    }
}

bool myStackEmpty(MyStack* obj) {
    return QueueEmpty(&(obj->q1)) && QueueEmpty(&(obj->q2));
}

void myStackFree(MyStack* obj) {
    // 记住还要free 队列
    QueueDestory(&(obj->q1));
    QueueDestory(&(obj->q2));

    free(obj);
    obj = NULL;
}

/**
 * Your MyStack struct will be instantiated and called as such:
 * MyStack* obj = myStackCreate();
 * myStackPush(obj, x);
 
 * int param_2 = myStackPop(obj);
 
 * int param_3 = myStackTop(obj);
 
 * bool param_4 = myStackEmpty(obj);
 
 * myStackFree(obj);
*/

用栈实现队列

typedef int STDataType;

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

void StackInit(stack* ps);
void StackDestroy(stack* ps);
void StackPush(stack* ps, STDataType data);

STDataType StackTop(stack* ps);

void StackPop(stack* ps);

bool StackEmpty(stack* ps);

int StackSize(stack* ps);
void StackInit(stack* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}
void StackDestroy(stack* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}
void StackPush(stack* ps, STDataType data)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* temp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newcapacity);
		assert(temp);
		ps->a = temp;
		ps->capacity = newcapacity;
	}
	ps->a[ps->top] = data;
	ps->top++;
}

STDataType StackTop(stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->a[ps->top - 1];
}

void StackPop(stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	ps->top--;
}

bool StackEmpty(stack* ps)
{
	assert(ps);

	return ps->top == 0;
}

int StackSize(stack* ps)
{
	assert(ps);
	int size = 0;
	for (int i = 0; i < ps->top; i++)
	{
		size++;
	}
	return size;
}

typedef struct {
    stack InQ;
    stack OutQ;
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
    StackInit(&obj->InQ);
    StackInit(&obj->OutQ);
    return obj;
}

void myQueuePush(MyQueue* obj, int x) {
    StackPush(&obj->InQ, x);
}

int myQueuePop(MyQueue* obj) {
    if(StackEmpty(&obj->OutQ))
    {
        while(!StackEmpty(&obj->InQ))
        {
            StackPush(&obj->OutQ, StackTop(&obj->InQ));
            StackPop(&obj->InQ);
        }
    }
    STDataType data = StackTop(&obj->OutQ);
    StackPop(&obj->OutQ);
    return data;
}

int myQueuePeek(MyQueue* obj) {
    if(StackEmpty(&obj->OutQ))
    {
        while(!StackEmpty(&obj->InQ))
        {
            StackPush(&obj->OutQ, StackTop(&obj->InQ));
            StackPop(&obj->InQ);
        }
    }
    STDataType data = StackTop(&obj->OutQ);
    return data;
}

bool myQueueEmpty(MyQueue* obj) {
    return StackEmpty(&obj->InQ) && StackEmpty(&obj->OutQ);
}

void myQueueFree(MyQueue* obj) {
    StackDestroy(&obj->InQ);
    StackDestroy(&obj->OutQ);
    free(obj);
    obj = NULL;
}

调试接口性OJ题,快速构建链表测试

在这里插入图片描述

循环队列

实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型
时可以就会使用循环队列。环形队列可以使用数组实现,也可以使用循环链表实现。
在这里插入图片描述
使用数组来实现循环队列,因为数组的存储空间是连续的可以通过下标访问,容易找到某一个元素它的前一个元素,而队列需要循环找前一个元素,
在这里插入图片描述
在这里插入图片描述

typedef struct {
    int* a;
    int head;
    int tail;
    int k;

} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue*obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    obj->a = (int*)malloc(sizeof(int)*(k+1));
    obj->head = obj->tail = 0;
    obj->k = k;
    return obj;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->head == obj->tail;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    int next = obj->tail + 1;
    if(next == obj->k+1)
        next = 0;
    return next == obj->head;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj))
        return false;
    obj->a[obj->tail] = value;
    obj->tail++;
    if(obj->tail == obj->k + 1)
        obj->tail = 0;
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return false;
    obj->head++;
    if(obj->head == obj->k + 1)
        obj->head = 0;
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return -1;
    return obj->a[obj->head];
}

int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return -1;
    int prev = obj->tail-1;
    if(prev < 0)
        prev = obj->k+1-1;
    return obj->a[prev];
}


void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);
    free(obj);
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值