关于栈和队列入门

栈和队列的区别是啥?吃多了拉就是队列;吃多了吐就是栈


栈(stack)

栈是一种线性数据结构,具有后进先出(Last In First Out,LIFO)的特点。栈的基本操作包括入栈(push)和出栈(pop),入栈将元素压入栈顶,出栈将栈顶元素弹出。栈还有一个重要的操作是查看栈顶元素(top),但不弹出。栈可以用数组或链表实现。

小问题:数组的首地址做栈顶还是栈底比较好?

答:数组的首地址做栈底比较好,因为栈顶要进行元素的插入和删除操作,所以数组尾部跟适合比较频繁插入和删除

// 栈的流程图

push:
1. 判断栈是否已满
2. 将元素插入栈顶
3. 栈顶指针加1

pop:
1. 判断栈是否为空
2. 取出栈顶元素
3. 栈顶指针减1

直接上代码

1.创建栈结构体的过程

#include <stdio.h>
#include <stdlib.h>

#define MAX_SIZE 100
typedef struct {
    int data[MAX_SIZE];
    int top; // 栈顶指针
    int size // 栈的大小(栈中元素个数) 
} Stack;
// 这里定义了一个栈结构体,包含了栈的数据和栈顶指针,方便后续的栈操作。

2.栈的初始化

SeqStack create(){
    //创建栈,相当于动态开辟一个数组出来
    SeqStack p=(Stack *)malloc(sizeof(Stack));
    if(p==NULL){
        return NULL;
    }
    //初始化栈的大小
    p->size=0;
    //初始化栈中元素
    for(int i=0;i<MAX;i++){
        p->data[i]=0;
    }
    return p;
}

3.入栈

void push(SeqStack stack,int data){
    if(stack==NULL){
        return;
    }
    //入栈需要判断栈是否已满
    if(stack->size==MAX){
        printf("栈已满");
        return;
    }
    //stack->size  栈的大小就是我们插入元素的下一个位置
    stack->data[stack->size]=data;
    //改变栈的大小
    stack->size++;
}

入栈 需要注意 栈是否为空 栈是否已满

4.出栈

void pop(SeqStack stack){
    if(stack==NULL){
        return;
    }
    if(stack->size==0){
        printf("栈已空!\n");
        return;
    }
    //删除一个元素
    stack->data[stack->size-1]=0;
    //改变栈的大小
    stack->size--;
}

 出栈 需要注意 栈是否不存在 和 栈是否已空

 5.最后遍历栈中元素

void foreachStack(SeqStack stack){
    if(stack==NULL){
        return;
    }
    for(int i=0;i<stack->size;i++){
        printf("%d ",stack->data[i]);
    }
    
}

x.当然我们也可以选择这样写

#include <stdio.h>
#include <stdlib.h>

#define MAX_SIZE 100
typedef struct {
    int data[MAX_SIZE];
    int top; // 栈顶指针
} Stack;

void SeStack(Stack *s) {
    s->top = -1; // 初始化栈顶指针为-1,表示栈为空
}

int is_empty(Stack *s) {
    return s->top == -1; // 栈顶指针为-1时栈为空
}

int is_full(Stack *s) {
    return s->top == MAX_SIZE - 1; // 栈顶指针为MAX_SIZE-1时栈为满
}

void push(Stack *s, int x) {
    if (is_full(s)) {
        printf("Error: stack is full\n");
        exit(-1);
    }
    s->data[++s->top] = x; // 将元素插入栈顶
}

int pop(Stack *s) {
    if (is_empty(s)) {
        printf("Error: stack is empty\n");
        exit(-1);
    }
    // 这里是判断栈是否为空的代码,如果为空则输出错误信息并退出程序。
    return s->data[s->top--]; // 取出栈顶元素并将栈顶指针减1
}

队列(Queue)

队列是一种线性数据结构,它具有先进先出(FIFO)的特点。队列有两个指针,一个指向队头,一个指向队尾。当元素被插入队列时,它被插入到队尾,当元素被删除时,它被删除队头。队列可以用数组或链表实现。在数组实现中,队列的大小是固定的,当队列满时,无法插入新元素。在链表实现中,队列的大小是动态的,可以插入任意数量的元素。队列常用于模拟系统,如操作系统中的进程调度,网络中的数据传输等。

 小问题:数组的首地址做 队头 好还是 队尾 好?

答:都一样,做队头和队尾差别不大,因为都需要移动大量元素

直接上代码

1.创建队列的结构体

#include <stdio.h>
#include <stdlib.h>

#define MAX_SIZE 100
typedef struct {
    int data[MAX_SIZE];
    int front; // 队头指针
    int rear; // 队尾指针
} Queue,*SeqQueue;
// 这里定义了一个队列结构体,包含了队列的数据和队头、队尾指针,方便后续的队列操作。

 2.隊列的初始化(数组头做队头,数组尾做队尾)

SeqQueue int(){
    //申請隊列空間即數組空間
    SeqQueue p=(Queue *)malloc(sizeof(Queue));
    
    if(p==NULL){
        return NULL;
    }
    
    //初始化隊列大小
    p->size=0;
    
    for(int i=0;i<MAX;i++){
        p->data[i]=0;
    }
    return p;
}

 3.入隊

void push(SeqQueue p,int value){
    if(p==NULL){
        return;     //隊列不存在
    }
    if(p->size==MAX){
        printf("隊列元素已滿!\n");
        return;
    }
    //進隊
    p->data->size=value;
	
    //改變隊列元素個數
    p->size++;
}

4.出隊

void push(SeqQueue p,int value){
    if(p==NULL){
        return;     //隊列不存在
    }
    if(p->size==0){
        printf("隊列元素已空!\n");
        return;
    }
    //出隊   刪除數組首元素
    for(int i=0;i<p->size;i++)
	
    //改變隊列元素個數
    p->size--;
}

要記得 看到循環裏面有 i+1 的時候,要改變最終值

x.我们也可以这样写

#include <stdio.h>
#include <stdlib.h>

#define MAX_SIZE 100
typedef struct {
    int data[MAX_SIZE];
    int front; // 队头指针
    int rear; // 队尾指针
} Queue;
// 这里定义了一个队列结构体,包含了队列的数据和队头、队尾指针,方便后续的队列操作。

void init(Queue *q) {
    q->front = q->rear = 0; // 初始化队头和队尾指针
}

int is_empty(Queue *q) {
    return q->front == q->rear; // 队头和队尾指针相等时队列为空
}

int is_full(Queue *q) {
    return (q->rear + 1) % MAX_SIZE == q->front; // 队尾指针加1取模后等于队头指针时队列为满
}

void enqueue(Queue *q, int x) {
    if (is_full(q)) {
        printf("Error: queue is full\n");
        exit(-1);
    }
    q->data[q->rear] = x; // 将元素插入队尾
    q->rear = (q->rear + 1) % MAX_SIZE; // 队尾指针加1取模
}

int dequeue(Queue *q) {
    if (is_empty(q)) {
        printf("Error: queue is empty\n");
        exit(-1);
    }
    int x = q->data[q->front]; // 取出队头元素
    q->front = (q->front + 1) % MAX_SIZE; // 队头指针加1取模
    return x;
}

小问题:链表的 头结点端 做队头还是队尾?

答:做队头好 因为头结点端进行删除方便 尾端插入元素方便(尾插法)

更多

栈和队列是常用的数据结构,它们在计算机科学中有着广泛的应用。栈的特点是后进先出(LIFO),它可以用于表达式求值、函数调用、括号匹配等场景。队列的特点是先进先出(FIFO),它可以用于模拟系统、网络数据传输等场景。在实际开发中,我们经常会用到栈和队列,因此熟练掌握它们的使用方法是非常重要的。

如何学习

1. 了解栈和队列的定义和特点,理解它们的应用场景。
2. 学习栈和队列的基本操作,包括入栈、出栈、入队、出队等。
3. 熟悉栈和队列的实现方式,包括数组和链表实现。
4. 练习栈和队列的应用,如表达式求值、函数调用、括号匹配、模拟系统、网络数据传输等。
5. 多做练习,加深对栈和队列的理解和掌握。

栈和队列的拓展与运用包括但不限于以下内容:


1. 栈和队列的应用拓展,如栈的应用可以包括中缀表达式转后缀表达式、栈的应用可以包括括号匹配问题的求解等。
2. 栈和队列的优化,如栈的优化可以包括空间复杂度的优化、栈的优化可以包括时间复杂度的优化等。
3. 栈和队列的实现方式的拓展,如栈的实现方式可以包括链式栈的实现、队列的实现方式可以包括循环队列的实现等。
4. 栈和队列的应用案例,如栈的应用案例可以包括浏览器的前进后退功能的实现、队列的应用案例可以包括操作系统中进程调度算法的实现等。
5. 栈和队列的算法分析,如栈和队列的算法分析可以包括时间复杂度和空间复杂度的分析等。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值