数据结构(2)—— 栈和队列

本文介绍了栈和队列这两种基本数据结构的实现方法,包括栈的顺序结构和链式结构,以及队列的顺序结构和链式结构实现。此外,还探讨了如何使用两个栈来实现队列的功能。

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

1 栈的两种物理结构实现

堆栈基本特征: 先进后出,后进先出(类似垃圾箱)
栈顶指针用来记录最后进入数据的位置。

1.1 栈的顺序结构实现

/*栈练习,顺序存储结构实现*/
#include<stdio.h>
#include<stdbool.h>

int stack[10];
int size;//表示栈中有效数据个数

//判断是否为空
bool is_empty(){
    return !size;
}

//判断是否为满
bool is_full(){
    return size == 10;
}

//初始化
void init(){
}

//销毁
void destroy(){
    size = 0;
}

//加入数据(压入)
void push(int num){
    stack[size] = num;
    size++;
}

//拿出数据(弹出)
void pop(){
    size--;
}

//获取数据
int peak(){
    return stack[size - 1];
}

int main(){
    push(1);
    push(2);
    push(3);
    printf("%-3d",peak());
    pop();
    printf("%-3d",peak());
    pop();
    push(4);
    printf("%-3d",peak());
    pop();
    printf("%-3d",peak());
    pop();
    printf(is_empty()?"空\n":"非空\n");
    return 0;
}

1.2 栈的链式结构实现

/*栈练习,链式存储结构实现*/
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>

typedef struct node{
    int num;
    struct node *p_next;
}node;
void pop();
node head;//头结点

//判断是否为空
bool is_empty(){
    return !head.p_next;
}

//判断是否为满
bool is_full(){
    return false;
}

//初始化
void init(){
}

//销毁
void destroy(){
    while (head.p_next){
        pop();
    }
}

//加入数据(压入)
void push(int num){
    node *p_node = (node *)malloc(sizeof(node));
    if (!p_node){
        return;
    }
    p_node->num = num;
    p_node->p_next = head.p_next;
    head.p_next = p_node;
}

//拿出数据(弹出)
void pop(){
    if (head.p_next){
        node *p_tmp = head.p_next;
        head.p_next = p_tmp->p_next;
        free(p_tmp);
        p_tmp = NULL;
    }
}

//获取数据
int peak(){
    if (head.p_next){
        return head.p_next->num;
    }
    else {
        return -1;
    }
}

int main(){
    push(1);
    push(2);
    push(3);
    printf("%d ",peak());
    pop();
    printf("%d ",peak());
    pop();
    push(4);
    printf("%d ",peak());
    pop();
    printf("%d ",peak());
    pop();
    printf(is_empty()?"空\n":"非空\n");
    destroy();//必须释放内存,否则就会造成内存泄漏
    return 0;
}

2 队列的两种物理结构实现

队列的基本特征:先进先出(FIFO)。
所有数据有两个端点,一端输入数字另一端输出数字。

2.1 队列的顺序结构实现

/*顺序结构实现队列*/
#include<stdio.h>
#include<stdbool.h>

int queue[10];
int head,tail;//head记录下一个要拿的数据的下标,tail记录下一个要放的数据的下标

bool is_empty(){
    return head == tail;
}

bool is_full(){
    return tail > 9;
}

void init(){
    head = 0;
    tail = 0;
}

void destroy(){
    head = 0;
    tail = 0;
}

void push(int num){
    queue[tail] = num;
    tail++;
}

void pop(){
    head++;
}

int peak(){
    return queue[head];
}

int main(){
    int num = 1;
    while (!is_full()){
        push(num);
        num++;
    }       
    while (!is_empty()){
        printf("%d ",peak());
        pop();
    }
    printf("\n");
    printf(is_full() ? "满\n" : "不满\n");
    return 0;
}

  这个队列的实现,还存在缺陷,head和tail都只能加,不能减,不能实现现实中的真正的队列,像这里最后明明是空的,但是却判断为满,而不能再用,怎么改一下呢?

/*顺序结构实现循环队列*/
#include<stdio.h>
#include<stdbool.h>

int queue[3];
int head,tail,size;//head记录下一个要拿的数据的下标,tail记录下一个要放的数据的下标

bool is_empty(){
    return !size;
}

bool is_full(){
    return size == 3;
}

void init(){
    head = 0;
    tail = 0;
    size = 0;
}

void destroy(){
    head = 0;
    tail = 0;
    size = 0;
}

void push(int num){
    queue[tail] = num;
    tail = (tail + 1) % 3;
    size++;
}

void pop(){
    head = (head + 1) % 3;
    size--;
}

int peak(){
    return queue[head];
}

int main(){
    int num = 1;
    while (!is_full()){
        push(num);
        num++;
    }       
    while (!is_empty()){
        printf("%d ",peak());
        pop();
    }
    printf("\n");
    printf(is_full() ? "满\n" : "不满\n");
    for (num = 1;num <= 3;num++){
        push(num);
    }
    while (!is_empty()){
        printf("%d ",peak());
        pop();
    }
    printf("\n");
    return 0;
}

2.2 队列的链式结构实现

/*队列练习,链式结构实现*/
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>

typedef struct node{
    int num;
    struct node *p_next;
}node;
node head;
void pop();

bool is_empty(){
    return !head.p_next;
}

bool is_full(){
    return false;
}

void init(){
}

void destroy(){
    while (head.p_next){
        pop();
    }
}

void push(int num){
    node *p_tmp = &head;
    node *p_node = (node *)malloc(sizeof(node));
    p_node->num = num;
    p_node->p_next = NULL;
    while (p_tmp->p_next){
        p_tmp = p_tmp->p_next;
    }
    p_tmp->p_next = p_node;
}

void pop(){
    if (head.p_next){
        node *p_tmp = head.p_next;
        head.p_next = p_tmp->p_next;
        free(p_tmp);
        p_tmp = NULL;
    }
}

int peak(){
    if (head.p_next){
        return head.p_next->num;
    }
    else {
        return -1;
    }
}

int main(){
    init();
    push(1);
    push(2);
    push(3);
    printf("%d ",peak());
    pop();
    printf("%d ",peak());
    pop();
    printf("%d\n",peak());
    printf(is_empty() ? "空\n" : "非空\n");
    destroy();
    return 0;
}

  最后,还有个好玩的,就是用堆栈来实现队列,这个怎么做呢?
  我们可以申请两个堆栈,堆栈1用于输入,堆栈2用于输出。压入时只管往堆栈1中push,弹出的时候,就要注意了。在堆栈2为NULL时,倒数据,并把堆栈1中的数据倒空,然后直至弹空后,可再往堆栈2中倒数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值