栈和队列

本文详细介绍了栈和队列这两种基本的数据结构。栈是一种只允许在一端进行插入和删除操作的线性表,遵循后进先出原则;队列允许一端插入数据,另一端删除数据,遵循先进先出原则。文章提供了栈和队列的操作实现,并通过测试用例验证了功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

栈的相关操作

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操
作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。不含任
何元素的栈称为空栈,栈又称为后进先出的线性表。
栈功能:将数据从一种序列改变到另一种序列

Stack.h

typedef struct Stack
{
    DataType* _array;
    size_t _top;//栈顶
    size_t _end;//栈底
}Stack;

//栈的实现接口
void StackInit(Stack *s);
void StackPush(Stack* s,DataType x);
void StackPop(Stack* s);
DataType StackTop(Stack* s);
size_t StackSize(Stack* s);
int StackEmpty(Stack* s);
//栈的初始化
void StackInit(Stack *s)
{
    assert(s);
    s->_array = NULL;
    s->_end = 0;
    s->_top = 0;
}
//入栈
void StackPush(Stack* s, DataType x)
{

    if (s->_top == s->_end)//栈中只有一个元素
    {
    //开辟空间
    size_t size = s->_end > 0 ? s->_end * 2 : 3;
    s->_array = (DataType*)realloc(s->_array, size*sizeof(DataType));
    assert(s->_array);
        s->_end = size;
    }

    s->_array[s->_top++] = x;
}
//出栈
void StackPop(Stack* s)
{
    assert(s);
    if (s->_top > 0)
        (--s)->_top;
}
//获得栈顶元素

DataType StackTop(Stack* s)
{
    assert(s);
    return s->_array[s->_top - 1];
}
//栈的大小
size_t StackSize(Stack* s)
{
    assert(s);
    return s->_top;
}
//栈是否为空

int StackEmpty(Stack* s)
{
    assert(s);
    return s->_top;//返回0则栈为空
}
//测试用例

void TestStack()
{
    Stack s;
    StackInit(&s);
    StackPush(&s, 1);
    StackPush(&s, 2);
    StackPush(&s, 3);
    StackPush(&s, 4);
    StackPush(&s, 6);
    StackPush(&s, 7);
    StackPush(&s, 8);

    while(StackEmpty(&s))//栈不为空时
    {
        printf("%d ", StackTop(&s));
        StackPop(&s);
    }
    printf("\n");


}

Test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include <assert.h>
#include <stdio.h>
#include <windows.h>
#include <string.h>

#include "Stack.h"

int main()
{
    //TestStack();
    system("pause");
    return 0;
}

队列的相关操作

只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性
表 ,进行插入操作的一端称为队尾(入队列) ,进行删除操作的一端称为队头(出队列),遵循先入先出的原则

Queue.h

#pragma once
typedef int DataType;
typedef struct QueueNode
{
    DataType _data;
    struct QueueNode* _next;
}QueueNode;

typedef struct Queue
{
    QueueNode* _head;//队头
    QueueNode* _tail;//队尾
}Queue;

void QueueInit(Queue* q);
void QueuePush(Queue* q, DataType x);
void QueuePop(Queue* q);
DataType QueueFront(Queue* q);
DataType QueueBack(Queue* q);
size_t QueueSize(Queue* q);
int QueueEmpty(Queue* q);
//队列初始化
void QueueInit(Queue* q)
{
    assert(q);
    q->_head = q->_tail = NULL;

}

//入队列
void QueuePush(Queue* q, DataType x)
{
    QueueNode* node = NULL;
    assert(q);
    node = (QueueNode*)malloc(sizeof(QueueNode));
    node->_next = NULL;
    node->_data = x;
    //判断q->_tail
    if (q->_tail == NULL)
    {
        q->_head = q->_tail = node;
    }
    else
    {
        q->_tail->_next = node;
        q->_tail = node;
    }


}
//出队列
void QueuePop(Queue* q)
{

    assert(q);
    if (q->_head==q->_tail)
    {
        if (q->_head)
        {
            free(q->_head);
            q->_head = q->_tail = NULL;
        }
    }
    else
    {
           //多个节点 
        QueueNode* next = q->_head->_next;
        free(q->_head);
        q->_head = next;
    }
}
//队头
DataType QueueFront(Queue* q)
{
    assert(q);
    return q->_head->_data;
}
//队尾
DataType QueueBack(Queue* q)
{
    assert(q);
    return q->_tail->_data;
}
//队列大小
size_t QueueSize(Queue* q)
{
    assert(q);
    QueueNode* cur = NULL;
    size_t size = 0;
    cur = q->_head;
    while (cur != NULL)
    {
        size++;
        cur = cur->_next;
    }
    return size;
}
//队列是否为空
int QueueEmpty(Queue* q)
{
    assert(q);
    return q->_head==NULL ? 0 : 1;
}
//测试用例
void TestQueue()
{
    Queue q;
    QueueInit(&q);
    QueuePush(&q, 1);
    QueuePush(&q, 2);
    QueuePush(&q, 3);
    QueuePush(&q, 4);
    QueuePush(&q, 5);

    while (QueueEmpty(&q))//队列不为空时
    {
        printf("%d ", QueueFront(&q));
        QueuePop(&q);
    }
    printf("\n");
}

Test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <windows.h>

#include "Queue.h"
int main()
{
    TestQueue();
    system("pause");
    return 0;
}

这里补充一下,队列容易产生溢出:
假溢出:顺序队列因多次入队列和出队列操作后出现的尚有存储空间但不
能再进行入队列操作的溢出
真溢出:顺序队列最大存储空间已经存满而又要求进行入队列操作所引起
的溢出。
解决假溢出的办法就是循环队列,即将头尾相接的顺序存储队列。
那么循环队列如何判断队列空和满呢?

  1. 少用一个存储单元
  2. 设置一个标志位
  3. 设置一个计数器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值