数据结构——栈和队列1

发布于:2025-08-13 ⋅ 阅读:(16) ⋅ 点赞:(0)

1.栈

1.1 概念与结构

栈:一种特殊的线性表,只允许在固定的一端进行插入和删除数据操作。进行数据的插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据遵循先进后出的原则。

压栈:栈的插入操作称为进栈/压栈/入栈,入数据在栈顶。

出栈:栈的删除操作叫做出栈。出数据也在栈顶。

栈底层结构选型:

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

1.2栈的实现

Stack.c
#include"Stack.h"

//栈的初始化
void StackInit(Stack* ps) {
	assert(ps);
	ps->arr = NULL;
	ps->top = ps->capacity = 0;
}

//栈的销毁
void StackDestroy(Stack* ps) {
	if (ps->arr != NULL)
		 free(ps->arr);
	ps->arr = NULL;
	ps->top = ps->capacity = 0;

}


//入栈 --  栈顶  -- 顺序表的尾插
void StackPush(Stack* ps, STDataType x) 
{
	assert(ps);
	//空间不够 --- 增容
	if (ps->top == ps->capacity)
	{
		//扩容
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* tmp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!\n");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newCapacity;
		

	}
	//空间足够 --- 直接插入数据
	ps->arr[ps->top] = x;
	ps->top++;

	
}

//判空
bool StackEmpty(Stack* ps)
{
	assert(ps);
	return ps->top == NULL;
	//top=NULL   返回 true
	//top!=NULL  返回 false
}

//出栈  -- 栈顶
void StackPop(Stack* ps)
{
	assert(!StackEmpty(ps));
	ps->top--;
}

//取栈顶元素
STDataType StackTop(Stack* ps) 
{
	assert(!StackEmpty(ps));
	return ps->arr[ps->top - 1];
	
}

2.队列

2.1 概念与结构

概念:只允许在一段进行数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出的特点。

入队列:进行插入操作的一端称为队尾

出队列:进行删除操作的一端称为队头

队列底层结构选型

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

2.2 队列的实现

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;

//这样定义了头结点和尾节点会使入队列和出队列的复杂度为O(1)


//初始化
void QueueInit(Queue* pq);

//入队列
void QueuePush(Queue* pq, QDataType x);

//出队列
void QueuePop(Queue* pq);

//判空
bool QueueEmpty(Queue* pq);

//计算队列里面的数据个数
QDataType QueueSize(Queue* pq);

//取队列头数据
QDataType QueueFront(Queue* pq);

//取队列尾数据
QDataType QueueBack(Queue* pq);

//销毁队列
void QueueDestroy(Queue* pq);
Queue.c
#include"Queue.h"


//初始化
void QueueInit(Queue* pq) {
	assert(pq);
	//队列里面只有phead和ptail

	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

//入队列
void QueuePush(Queue* pq, QDataType x) {
	assert(pq);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		perror("malloc fail!\n");
		exit(1);
	}
	newnode->data = x;
	newnode->next = NULL;
	//队列为空,队头队尾都是newnode
	if (pq->phead == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else {
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;

}

//判空
bool QueueEmpty(Queue* pq) {
	assert(pq);
	return pq->phead == NULL;  //pq->phead为空,返回true
	
}

//计算队列里面的有效元素个数
QDataType QueueSize(Queue* pq)
{
	
	//QueueNode* pcur = pq->phead;
	//int size = 0;
	//while (pcur)
	//{
	//	size++;
	//	pcur = pcur->next;
	//	//时间复杂度为O(N)
	//	//其余的队列接口复杂度都是O(1)
	//	//尝试换一种方法来实现,达到此接口的时间复杂度为O(1)
	//}
	//return size;
	
	return pq->size;
}


//出队列
void QueuePop(Queue* pq) {
	assert(pq);//传过来的pq不为空 or 有效的队列结构
	assert(!QueueEmpty(pq));//空队列不可取出数据
	//只有一个节点
	if (pq->phead == pq->ptail)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else {
		QueueNode* next=pq->phead->next;
		free(pq->phead);
		pq->phead = next;

	}
	pq->size--;

}

//取队列头数据
QDataType QueueFront(Queue* pq)
{
	assert(pq);//传过来的pq不为空 or 有效的队列结构
	assert(!QueueEmpty(pq));//空队列不可取出数据
	return pq->phead->data;
}

//取队列尾数据
QDataType QueueBack(Queue* pq) {
	assert(pq);//传过来的pq不为空 or 有效的队列结构
	assert(!QueueEmpty(pq));//空队列不可取出数据
	return pq->ptail->data;
}

//销毁队列
void QueueDestroy(Queue* pq) {
	assert(pq);
	QueueNode* pcur = pq->phead;
	while (pcur)
	{
		QueueNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	pq->phead = pq->ptail = NULL;
	//将队列的两个指针置为空,防止变为野指针
	pq->size = 0;
}

3. 栈和队列算法题

3.1 有效的括号

typedef char STDataType;
//定义栈的数据结构
//栈的底层结构 链表或者是数组都是可以的 但是数组的实现会更加简单(有点像顺序表) 

typedef struct Stack {
	STDataType* arr;
	int top;
	int capacity;
}Stack;
//栈的初始化
void StackInit(Stack* ps) {
	assert(ps);
	ps->arr = NULL;
	ps->top = ps->capacity = 0;
}

//栈的销毁
void StackDestroy(Stack* ps) {
	if (ps->arr != NULL)
		 free(ps->arr);
	ps->arr = NULL;
	ps->top = ps->capacity = 0;

}


//入栈 --  栈顶  -- 顺序表的尾插
void StackPush(Stack* ps, STDataType x) 
{
	assert(ps);
	//空间不够 --- 增容
	if (ps->top == ps->capacity)
	{
		//扩容
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* tmp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!\n");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newCapacity;
		

	}
	//空间足够 --- 直接插入数据
	ps->arr[ps->top] = x;
	ps->top++;

	
}

//判空
bool StackEmpty(Stack* ps)
{
	assert(ps);
	return ps->top == NULL;
	//top=NULL   返回 true
	//top!=NULL  返回 false
}

//出栈  -- 栈顶
void StackPop(Stack* ps)
{
	assert(!StackEmpty(ps));
	ps->top--;
}

//取栈顶元素
STDataType StackTop(Stack* ps) 
{
	assert(!StackEmpty(ps));
	return ps->arr[ps->top - 1];
	
}

    //1.遇左括号入栈
    //2.遇右括号出栈,进行匹配,匹配不成功返回false,匹配成功,pi越界且栈为空返回true
    //3.只有一个左括号,pi越界的时候,且栈不为空,返回false
    //4.只有一个右括号,空栈不可进行出栈,返回false
bool isValid(char* s) {
    Stack st;
    StackInit(&st);
    char* pi=s;
    while(*pi!='\0')
    {
        if(*pi=='(' || *pi=='{' || *pi=='[')
        {
            //入栈
            StackPush(&st,*pi);
        }else
        {
            //取栈顶,进行匹配
            if(StackEmpty(&st))
            {
                //栈为空,说明只有有括号的情况,没有左括号
                StackDestroy(&st);
                return false;
            }
            char top=StackTop(&st);
            if((top=='(' && *pi !=')') 
                ||(top=='[' && *pi !=']') 
                ||(top=='{' && *pi !='}'))
                {
                    StackDestroy(&st);
                    return false;
                }
                //出栈
                StackPop(&st);
            
        }
        pi++;
        }
        
        
    
    //*pi='\0' 跳出循环 两种情况:1.栈为空返回是有效的字符串 2.栈不为空(只有左括号的字符)返回的是无效的字符串
    bool ret=StackEmpty(&st)? true :false;
    StackDestroy(&st);
    return ret;

}

栈和队列的算法题后续还有哟~~