ADT栈与队列的C语言编程与实现

一 、目的:

加深对抽象数据类型 ADT 栈和队列的理解;

二 、环境:

operating system version:Win11

CPU instruction set:  x64

Integrated Development Environment:Viusal Studio 2022

三 、内容:

编写程序实现ADT栈的定义,及常用操作(数组或指针实现

1) 生成栈

2) Push

3) Pop

编写程序实现ADT队列的定义,及常用操作:

1) 生成队列

2) Enqueues 入列

3) Isempty 判断是否队列为空 。

四 、步骤:

1.程序:

Part1:ADT栈的定义及常用操作

#include <stdio.h>  
#define MAXSIZE 100  
typedef struct node  
{  
    int* base;  
    int* top;  
    int stacksize;  
}Stack; //声明栈  
int InitStack(Stack& S);//初始化栈  
int Push(Stack& S, int e);//声明Push函数,实现压栈  
void Pop(Stack& S);//声明Pop函数,实现出栈  
int Get(Stack S);//声明Get函数,取出栈  
void PrintStack(Stack& S);//声明PrintStack函数,输出所有元素  
int main(int argc, char* argv[])  
{  
    int num;  
    int Value;  
    int choice;  
    Stack S;  
    if (InitStack(S))//根据返回值判断初始栈是否完成  
        printf("Initialization completed\n");  
    printf("Enter the number of data to be pushed into the stack:");  
    scanf_s("%d", &num);  
    printf("Start Push\n");//开始压栈  
    for (int n = 0; n < num; n++)  
    {  
        printf("Please enter the data %d :", n + 1);  
        scanf_s("%d", &Value);  
        Push(S, Value);  
    }  
    PrintStack(S);  
    printf("Whether to perform Pop, 0 -> no   others -> yes :");  
    scanf_s("%d", &choice);  
    if (choice)  
        Pop(S);  
    PrintStack(S);  
    return 0;  
}  
int InitStack(Stack& S)        //初始化栈空间      
{  
    S.base = new int[MAXSIZE];  
    if (!S.base) return 0;  
    S.top = S.base;  
    S.stacksize = MAXSIZE;  
    return 1;  
}  
int Push(Stack& S, int e)          //压栈      
{  
    if (S.top - S.base == S.stacksize) return 0;  
    S.top++;  
    *S.top = e;  
    return 1;  
}  
//出栈  
void Pop(Stack& S)      //删除栈顶元素并返回  
{  
    printf("The top-of-stack value of %d has been removed\n", *S.top);  
    S.top--;  
}  
int Get(Stack S)     //取栈  
{  
    if (S.top != S.base)  
        return *(S.top - 1);  
}  
void PrintStack(Stack& S)       //遍历栈  
{  
    int i;  
    if (S.top == S.base) printf("Stack empty\n");  
    else  
    {  
        printf("The data in the stack is\n");  
        i = S.top - S.base;  
        for (int j = 0; j < i; j++)  
        {  
            printf("%d\n", *(S.top - j));  
        }  
    }  
}  

Part2:ADT队列的定义及常用操作

#include<stdio.h>  
#include<stdlib.h>  
#include<string.h>  
  
typedef struct {             //定义队列类型  
    char data[1001];  
    int Front;  
    int Rear;  
    int Size;  
}Queue;  
void InitQueue(Queue* Q)    //初始化队列  
{  
    Q->Front = 0;  
    Q->Rear = 0;  
    Q->Size = 0;  
}  
int IsEmpty(Queue* Q)       //定义IsEmpty函数,判断队列是否为空  
{  
    return Q->Size == 0;  
}  
void EnQueue(Queue* Q, int x) //定义EnQueue函数,进行入队列  
{  
    Q->data[Q->Rear] = x;  
    Q->Rear++;  
    Q->Front = Q->Rear - 1;  
    Q->Size++;  
}  
  
int main()  
{  
    Queue Q;  
    InitQueue(&Q);//初始化队列  
    EnQueue(&Q, 5);   
    EnQueue(&Q, 20);  
    EnQueue(&Q, 3);  
    EnQueue(&Q, 5);  
    printf("\nGenerated Queue\n");  
  
    int m = Q.Rear;  
    for (int i = 0; i < m; i++)  
        printf("%d ", Q.data[i]);  
    if (IsEmpty(&Q))//判断是否空队列  
        printf("\nEmpty queue\n");  
    else  
        printf("\nQueue non-empty\n");  
    int f;  
    for (int k = 4; k < 1001; k++)  
    {  
        printf("\nEnter incoming queue number:");  
        scanf_s("%d", &f);  
        EnQueue(&Q, f);  
        printf("Result:");  
        m = Q.Rear;  
        int i;  
        for (i = 0; i < m; i++)  
            printf("%d ", Q.data[i]);  
        if (IsEmpty(&Q))  
            printf("\nEmpty queue\n");  
        else  
            printf("\nQueue non-empty\n");  
    }  
    return 0;  
} 

2.程序结果:

栈:

(1)首先进行初始化栈测试,这里通过InitStack()函数返回值来判断是否初始化成功。若初始化成功,则输出Initialization completed。

(2)压栈

输入测试数据2023,可见按照FILO原则,栈内保存状态为3202.

(3)出栈

在这里将栈顶元素3出栈,然后输出栈内剩余元素,如下图所示。

综上,编写程序实现ADT栈的定义及常用操作(数组或指针实现

1) 生成栈2) Push 3) Pop

队列:

(1)生成队列,如下图所示

(2)入列操作如下图所示,这里以15和25为例:

(3)Isempty判断队列是否为空,即队列size是否为0。如下图所示,可见队列非空。

编写程序实现ADT队列的定义,及常用操作:

1) 生成队列2) Enqueues 入列3) Isempty 判断是否队列为空 。

2.分析和改进:

在实现ADT栈的中,完成了最终的生成栈、push和pop的操作,运行效果也符合预期,但是在实际的分析中我发现最初的设计逻辑中在push操作中遗漏了栈空间的限制,在我的小样本测试中程序运行完美,但是若压栈的输入数据远远地超过了栈本身的容量,就会不可避免地造成爆栈的情况,因此,在实际的设计中还要考虑栈的空间,我后来改用了采用push函数返回值的判断方法在一定程度上避免了爆栈的可能。如下:

int Push(Stack& S, int e)          //压栈      
{  
    if (S.top - S.base == S.stacksize) return 0;  
    S.top++;  
    *S.top = e;  
    return 1;  
} 

五 小结:

此次有关于ADT栈和队列的实现,虽然对栈和队列概念已经较为熟悉,但是在实际的编程中仍然有一些细节没有注意到,例如在压栈的时候不能一味地考虑压入以及指针的变化,还应该考虑到栈的空间是否足够,以免出现爆栈的现象。

加强了我对于栈和队列的理解,也从实践的角度很好的掌握了栈和队列之间的区别。栈和队列是两种常用的数据结构,栈和队列是操作受限的线性表,栈和队列的数据元素具有单一的前驱和后继的线性关系;栈和队列又是两种重要的抽象数据类型。栈是限定在表尾进行插入和删除操作的线性表允许插入和删除的一端为栈顶,另一端为栈底,出栈元素只能是栈顶元素,后进先出,相邻元素具有前驱与后继关系。队列是只允许在一端进行插入操作,在另一端进行删除操作的线性表。允许插入的一端为队尾,允许删除的一端为队头,先进先出,相邻元素具有前驱与后继关系。

  • 15
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
循环队列是一种特殊的队列,它的队尾指针指向最后一个元素的下一个位置,队头指针指向队列中第一个元素。当队列满时,队尾指针和队头指针相等,但此时队列不是空的。 循环队列实现可以使用数组来存储元素,定义一个结构体来表示队列,其中包含队列的头指针、尾指针和数组元素。下面是循环队列ADT实现: ``` typedef struct { int *base; // 队列的存储空间 int front; // 队头指针 int rear; // 队尾指针 int size; // 队列的最大长度 } Queue; void InitQueue(Queue *q, int size) { q->base = (int *)malloc(size * sizeof(int)); q->front = q->rear = 0; q->size = size; } void EnQueue(Queue *q, int x) { if ((q->rear + 1) % q->size == q->front) { printf("Queue is full.\n"); return; } q->base[q->rear] = x; q->rear = (q->rear + 1) % q->size; } int DeQueue(Queue *q) { if (q->front == q->rear) { printf("Queue is empty.\n"); return -1; } int x = q->base[q->front]; q->front = (q->front + 1) % q->size; return x; } int GetQueueLength(Queue *q) { return (q->rear - q->front + q->size) % q->size; } ``` 使用循环队列可以方便地实现一些算法,如广度优先搜索(BFS)和滑动窗口等。下面是一个使用循环队列实现滑动窗口的例子: ``` void SlidingWindow(int *a, int n, int k) { Queue q; InitQueue(&q, k); int i; for (i = 0; i < k; i++) { while (GetQueueLength(&q) > 0 && a[i] >= a[q.base[q.rear-1]]) { DeQueue(&q); } EnQueue(&q, i); } for (; i < n; i++) { printf("%d ", a[q.base[q.front]]); while (GetQueueLength(&q) > 0 && a[i] >= a[q.base[q.rear-1]]) { DeQueue(&q); } while (GetQueueLength(&q) > 0 && q.base[q.front] <= i - k) { DeQueue(&q); } EnQueue(&q, i); } printf("%d\n", a[q.base[q.front]]); } ``` 该函数可以实现在一个长度为n的数组a中,找出每个长度为k的子数组中的最大值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

timerring

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值