【数据结构】栈和队列

目录

一、栈

1.1 基本概念

1.2 存储结构 

1.2.1 顺序栈

1.2.2 链式栈

二、队列

2.1 基本概念

2.2 存储结构

2.2.1 顺序队列

2.2.2 链式队列

三、总结


栈和队列是数据结构中比较基础的两种数据结构,它们都是线性结构,但是在数据存储和操作方式上有一些区别。本文将介绍栈和队列的基本概念、存储结构和操作方法。

一、栈

1.1 基本概念

栈是一种后进先出(Last In First Out,LIFO)的线性数据结构,它的特点是只能在固定的一端进行插入和删除操作。这一端被称为栈顶,另一端被称为栈底。

1.2 存储结构 

栈的存储结构有两种:顺序栈和链式栈。

1.2.1 顺序栈

顺序栈是利用数组实现的栈,它的操作比较简单,但是需要事先确定栈的大小

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

//定义:
#define MAXSIZE 100

typedef struct {
    int data[MAXSIZE];  // 存放栈中元素
    int top;            // 栈顶指针
} SqStack;

//初始化:
void InitStack(SqStack* S) {
    S->top = -1;        // 初始化栈顶指针为-1
}

//入栈:
bool Push(SqStack* S, int x) {
    if (S->top == MAXSIZE - 1) {    // 栈满
        return false;
    }
    S->data[++S->top] = x;          // 栈顶指针加1,将元素x入栈
    return true;
}

//出栈:
bool Pop(SqStack* S, int* x) {
    if (S->top == -1) {             // 栈空
        return false;
    }
    *x = S->data[S->top--];         // 将栈顶元素弹出,栈顶指针减1
    return true;
}

1.2.2 链式栈

链式栈是利用链表实现的栈,它的操作相对复杂,但是可以动态分配内存。

//定义:
typedef int STDataType;

typedef struct Stack
{
    STDataType* arr;
    int top;
    int capacity;
}Stack;


//初始化:
void StackInit(Stack* ps)
{
    STDataType* tmp = (STDataType*)malloc(sizeof(STDataType) * 4);
    if (tmp == NULL)
    {
        perror("malloc error");
    }
    ps->arr = tmp;
    ps->top = 0;
    ps->capacity = 4;
    return;
}

//入栈:
void StackPush(Stack* ps, STDataType x)
{
	assert(ps);
	assert(ps->arr);
    if (ps->top == ps->capacity)
    {
        STDataType* tmp = (STDataType*)realloc(ps->arr, sizeof(STDataType) * ps->capacity * 2);
        if (tmp == NULL)
        {
            perror("realloc error");
        }
        else
        {
            ps->arr = tmp;
            ps->capacity *= 2;
        }
    }
	ps->arr[ps->top] = x;
	ps->top++;
}

//获取栈顶元素
STDataType StackTop(Stack* ps)
{
    assert(ps);
    assert(ps->arr);
    assert(!StackEmpty(ps));

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

//检测栈是否为空
bool StackEmpty(Stack* ps)
{
    assert(ps);
    assert(ps->arr);
    return (ps->top == 0);
}

//栈中有效元素个数
int StackSize(Stack* ps)
{
    assert(ps);
    assert(ps->arr);
    return (ps->top);
}


// 销毁栈
void StackDestroy(Stack* ps)
{
    assert(ps);
    assert(ps->arr);
    free(ps->arr);
    free(ps);
}

二、队列

2.1 基本概念

队列是一种先进先出(First In First Out,FIFO)的线性数据结构,它的特点是只允许在一端(队尾)进行插入数据操作,在另一端(队头)进行删除数据操作。

2.2 存储结构

队列的存储结构有两种:顺序队列和链式队列。

2.2.1 顺序队列

顺序队列是利用数组实现的队列,它的操作比较简单,但是需要事先确定队列的大小。

//定义
#define MAXSIZE 100

typedef struct {
    int data[MAXSIZE];  // 存放队列中元素
    int front;          // 队头指针
    int rear;           // 队尾指针
} SqQueue;

//初始化
void InitQueue(SqQueue *Q) {
    Q->front = Q->rear = 0;     // 初始化队头和队尾指针为0
}

//入队
bool EnQueue(SqQueue *Q, int x) {
    if ((Q->rear + 1) % MAXSIZE == Q->front) {   // 队满
        return false;
    }
    Q->data[Q->rear] = x;                       // 将元素x入队
    Q->rear = (Q->rear + 1) % MAXSIZE;
    return true;
}

//出队
bool DeQueue(SqQueue *Q, int *x) {
    if (Q->front == Q->rear) {                  // 队空
        return false;
    }
    *x = Q->data[Q->front];                     // 将队头元素出队
    Q->front = (Q->front + 1) % MAXSIZE;
    return true;
}

2.2.2 链式队列

链式队列是利用链表实现的队列,它的操作相对复杂,但是可以动态分配内存。

typedef int QDataType;

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

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

//队列初始化
void QInit(Queue* pq)
{
	pq->head = NULL;
	pq->tail = NULL;
	pq->size = 0;
}

//入队
void QPush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* tmp = (QNode*)malloc(sizeof(QNode));
	if (tmp == NULL)
	{
		perror("malloc error");
	}
	tmp->data = x;
	tmp->next = NULL;
	if (QEmpty(pq))
	{
		pq->head = pq->tail = tmp;
	}
	else
	{
		pq->tail->next = tmp;
		pq->tail = tmp;
	}
	pq->size++;

}

//出队
void QPop(Queue* pq)
{
	assert(pq);
	assert(!QEmpty(pq));

	QNode* tmp = pq->head->next;
	free(pq->head);
	pq->head = tmp;

	pq->size--;
}

//队是否为空
bool QEmpty(Queue* pq)
{
	assert(pq);

	return (pq->size == 0);
}

//获取队头元素
QDataType QHeadData(Queue* pq)
{
	assert(pq);
	assert(pq->head);
	assert(!QEmpty(pq));

	return pq->head->data;
}

//获取队尾元素
QDataType QTailData(Queue* pq)
{
	assert(pq);
	assert(pq->tail);
	assert(!QEmpty(pq));

	return pq->tail->data;
}

//有效元素个数
int QSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}

//队列销毁
void QDestroy(Queue* pq)
{
	assert(pq);
	assert(pq->head);

	while (pq->head)
	{
		QPop(pq);
	}

	free(pq);
}

三、总结

栈和队列是数据结构中比较基础的两种数据结构,它们都是线性结构,但是在数据存储和操作方式上有一些区别。

栈的特点是后进先出,只能在一端进行插入和删除操作,存储结构有顺序栈和链式栈两种。

队列的特点是先进先出,只能在队尾插入元素,在队头删除元素,存储结构有顺序队列和链式队列两种。

在实际应用中,栈和队列都有广泛的应用,例如程序的函数调用、表达式求值、图的遍历等。掌握栈和队列的基本概念和操作方法,对于学习其他数据结构和算法具有重要的意义。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值