Day18、队列(顺序结构、链式结构)、循环队列、单向链表

本文介绍队列和链表两种数据结构的实现方法,包括队列的不同存储方式(顺序存储、循环队列、链式存储)及链表的基本操作(插入、删除等)。通过代码示例详细讲解各函数的实现原理。

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

队列:

定义:队列是一种数据结构,可以用来存储数字,在队列里是有顺序的

获得的数字是最先放进去的数字,先进先出

实现队列的用法需要提供一个函数用来向队列里放数字(PUSH),也需要一个函数从队列里获得数字(POP)

队列的顺序存储结构

编写函数模板

1 typedef struct{

 2     int buf[SIZE];

 3     int head;//第一个数字所在存储区的下标

 4     int tail;//第一个空位置所在的下标(最后一个数字的下一个下标 tail=size)

  5}queue;

  6//初始化函数

  7void queue_init(queue *p_queue){

 8     p_queue->head=0;

 9     p_queue->tail=0;

 10 }

 11//清理函数

 12void queue_deinit(queue *p_queue){

 13    p_queue->head=0;

 14    p_queue->head=0;

 15 }

 16//判断队列是否空的函数

 17int queue_empty(const queue *p_queue){

 18    return p_queue->head==p_queue->tail;

 19 }

 20//判断队列是否满的函数

 21int queue_full(const queue *p_queue){

 22    return p_queue->tail==SIZE;

 23 }

24 //获得数字个数的函数

 25int queue_size(const queue *p_queue){

 26    //每多一个数tail+1,每少一个数head加一

 27    return p_queue->tail-p_queue->head;

 28 }

 29//向队列里添加数字的函数

 30void queue_push(queue *p_queue,int num){//要修改队列,不能加const

 31    p_queue->buf[p_queue->tail]=num;

 32    p_queue->tail++;

 33 }

 34//从队列里拿走数字的函数

 35int queue_pop(queue *p_queue){

 36    int ret=p_queue->buf[p_queue->head];//队列是拿走先进来的数组

 37    p_queue->head++;

 38 }

 39//从队列里获得数字的函数

 40int queue_front(const queue *p_queue){

 41    return p_queue->buf[p_queue->head];//获得队列的头部

 42 }

编写源文件:01queue.c

#include "01queue.h"

//初始化函数

void queue_init(queue *p_queue) {

   p_queue->head = 0;

   p_queue->tail = 0;

}

//清理函数

void queue_deinit(queue *p_queue) {

   p_queue->head = 0;

   p_queue->tail = 0;

}

//判断队列是否空的函数

int queue_empty(const queue *p_queue) {

   return p_queue->head == p_queue->tail;

}

//判断队列是否满的函数

int queue_full(const queue *p_queue) {

   return p_queue->tail == SIZE;

}

//获得数字个数的函数

int queue_size(const queue *p_queue) {

   return p_queue->tail - p_queue->head;

}

//向队列里添加数字的函数

void queue_push(queue *p_queue, int num) {

   p_queue->buf[p_queue->tail] = num;

   p_queue->tail++;

}

//从队列里拿走数字的函数

int queue_pop(queue *p_queue) {

   int ret = p_queue->buf[p_queue->head];

   p_queue->head++;

   return ret;

}

//从队列里获得数字的函数

int queue_front(const queue *p_queue) {

    return p_queue->buf[p_queue->head];

}

改写成头文件:01queue.h

typedef struct {

   int buf[SIZE];

   int head/*第一个数字所在存储区的下标*/,tail/*第一个空位置所在的下标*/;

} queue;

//初始化函数

void queue_init(queue *);

//清理函数

void queue_deinit(queue *);

//判断队列是否空的函数

int queue_empty(const queue *);

//判断队列是否满的函数

int queue_full(const queue *);

//获得数字个数的函数

int queue_size(const queue *);

//向队列里添加数字的函数

void queue_push(queue *, int );

//从队列里拿走数字的函数

int queue_pop(queue *);

//从队列里获得数字的函数

int queue_front(const queue *);

#endif   //__01QUEUE_H__

编写主函数

#include <stdio.h>

#include "01queue.h"

int main() {

   queue que = {0};

   queue_init(&que);

   queue_push(&que, 10);

   queue_push(&que, 20);

   queue_push(&que, 30);

   queue_push(&que, 40);

   queue_push(&que, 50);

   queue_push(&que, 60);

   printf("数字个数是%d\n", queue_size(&que)); //计算一共放了几个

   printf("%d\n", queue_pop(&que)); //拿数

   printf("%d\n", queue_pop(&que));

   printf("%d\n", queue_pop(&que));

   printf("判断满的结果是%d\n", queue_full(&que));

   if (!queue_full(&que)) {

       queue_push(&que, 70);

       queue_push(&que, 80);

       printf("%d\n", queue_pop(&que));

       printf("%d\n", queue_pop(&que));

    }

   printf("%d\n", queue_pop(&que));

   printf("%d\n", queue_pop(&que));

   printf("%d\n", queue_pop(&que));

   printf("判断空的结果是%d\n", queue_empty(&que));

   queue_deinit(&que);

   return 0;

}

输入指令 gcc-DSIZE=6  1.c 01.c

        gcc -DSIZE=10  1.c 01.c

 

循环队列:编写队列,如果拿走头部的数,头部就空了,继续往队列放数,当放满了之后开始往头部放

编写源文件:02queue.c

#include "02queue.h"

//初始化函数

void queue_init(queue *p_queue) {

   p_queue->head = 0;

   p_queue->tail = 0;

   p_queue->num = 0;

}

//清理函数

void queue_deinit(queue *p_queue) {

   p_queue->head = 0;

   p_queue->tail = 0;

   p_queue->num = 0;

}

//判断队列是否空的函数

int queue_empty(const queue *p_queue) {  //不会做改变,加个const

   return !(p_queue->num);

}

//判断队列是否满的函数

int queue_full(const queue *p_queue) {

   return p_queue->num == SIZE;

}

//获得数字个数的函数

int queue_size(const queue *p_queue) {

   return p_queue->num;

}

//向队列里添加数字的函数

void queue_push(queue *p_queue, int num) { 

   p_queue->buf[p_queue->tail] = num; //用tail做下标找到这个数

   p_queue->num++;

    p_queue->tail = (p_queue->tail + 1) %SIZE;  //若尾部满了则绕回头部放数      

}

//从队列里拿走数字的函数

int queue_pop(queue *p_queue) {

   int ret = p_queue->buf[p_queue->head];

   p_queue->num--;

   p_queue->head = (p_queue->head + 1) % SIZE;

   return ret;

}

//从队列里获得数字的函数

int queue_front(const queue *p_queue) {

   return p_queue->buf[p_queue->head];

}

编写头文件:

#ifndef       __02QUEUE_H__

#define       __02QUEUE_H__

typedef struct {

   int buf[SIZE];

   int head/*第一个数字所在存储区的下标*/,tail/*第一个空位置所在的下标*/;

   int num;

} queue;

//初始化函数

void queue_init(queue *);

//清理函数

void queue_deinit(queue *);

//判断队列是否空的函数

int queue_empty(const queue *);

//判断队列是否满的函数

int queue_full(const queue *);

//获得数字个数的函数

int queue_size(const queue *);

//向队列里添加数字的函数

void queue_push(queue *, int );

//从队列里拿走数字的函数

int queue_pop(queue *);

//从队列里获得数字的函数

int queue_front(const queue *);

#endif   //__02QUEUE_H__

编写主函数: 02main.c

#include <stdio.h>

#include "02queue.h"

int main() {

   queue que = {0};

   queue_init(&que);   //初始化

   queue_push(&que, 10);  //放数

   queue_push(&que, 20);

   queue_push(&que, 30);

   queue_push(&que, 40);

   queue_push(&que, 50);

   queue_push(&que, 60);

   printf("数字个数是%d\n", queue_size(&que)); //计算一共放了几个

   printf("%d\n", queue_pop(&que));  //拿数

   printf("%d\n", queue_pop(&que));

   printf("%d\n", queue_pop(&que));

   printf("判断满的结果是%d\n", queue_full(&que));

   if (!queue_full(&que)) {

       queue_push(&que, 70);

       queue_push(&que, 80);

       printf("%d\n", queue_pop(&que));

       printf("%d\n", queue_pop(&que));

    }

   printf("%d\n", queue_pop(&que));

   printf("%d\n", queue_pop(&que));

   printf("%d\n", queue_pop(&que));

   printf("判断空的结果是%d\n", queue_empty(&que));

   queue_deinit(&que);  //清空

   return 0;

}

输入指令: gcc -DSIZE=6 02.c main2.c

执行结果:

数字个数是:6

10

20

30

判断满的结果是; 0

40

50

60

70

80

判断空的结果是:1   (1为真)

 

队列的链式存储结构:

 

编写源文件:03queue.c

#include <stdlib.h>

#include "03queue.h"

//初始化函数

void queue_init(queue *p_queue) {

   p_queue->head.p_next = &(p_queue->tail);

   p_queue->tail.p_next = NULL;

}

//清理函数

void queue_deinit(queue *p_queue) {

   while (p_queue->head.p_next != &(p_queue->tail)) {

       node *p_first = &(p_queue->head);

       node *p_mid = p_first->p_next;

       node *p_last = p_mid->p_next;

       p_first->p_next = p_last;

       free(p_mid);

       p_mid = NULL;

    }

}

//判断队列是否空的函数

int queue_empty(const queue *p_queue) {

   return p_queue->head.p_next == &(p_queue->tail);

}

//判断队列是否满的函数

int queue_full(const queue *p_queue) {

   return 0;

}

//获得数字个数的函数

int queue_size(const queue *p_queue) {

   int cnt = 0;

   const node *p_node = NULL;

   for (p_node = &(p_queue->head);p_node !=&(p_queue->tail);p_node = p_node->p_next) {

       const node *p_first = p_node;

       const node *p_mid = p_first->p_next;

       const node *p_last = p_mid->p_next;

       if (p_mid != &(p_queue->tail)) {

           cnt++;

       }

    }

   return cnt;

}

//向队列里添加数字的函数

void queue_push(queue *p_queue, int num) {

   node *p_node = NULL;

   node *p_tmp = (node *)malloc(sizeof(node));

   if (!p_tmp) {  //如果分配失败,则返回

       return ;

    }

   p_tmp->num = num;   //如果分配成功

   p_tmp->p_next = NULL;

   for (p_node = &(p_queue->head);p_node !=&(p_queue->tail);p_node = p_node->p_next) {

       node *p_first = p_node;

       node *p_mid = p_first->p_next;

       node *p_last = p_mid->p_next;

       if (p_mid == &(p_queue->tail)) {

           p_first->p_next = p_tmp;

           p_tmp->p_next = p_mid;

           break;

        }

    }

}

//从队列里拿走数字的函数

int queue_pop(queue *p_queue) {

   node *p_first = NULL, *p_mid = NULL, *p_last = NULL;

   int ret = p_queue->head.p_next->num;

   p_first = &(p_queue->head);

   p_mid = p_first->p_next;

   p_last = p_mid->p_next;

   p_first->p_next = p_last;

   free(p_mid);

   p_mid = NULL;

   return ret;

}

//从队列里获得数字的函数

int queue_front(const queue *p_queue) {

   return p_queue->head.p_next->num;

}

编写头文件:03queue.h

#ifndef       __03QUEUE_H__

#define       __03QUEUE_H__

typedef struct node {

   int num;

   struct node *p_next;

} node;

typedef struct {

   node head, tail;

} queue;

//初始化函数

void queue_init(queue *);

//清理函数

void queue_deinit(queue *);

//判断队列是否空的函数

int queue_empty(const queue *);

//判断队列是否满的函数

int queue_full(const queue *);

//获得数字个数的函数

int queue_size(const queue *);

//向队列里添加数字的函数

void queue_push(queue *, int );

//从队列里拿走数字的函数

int queue_pop(queue *);

//从队列里获得数字的函数

int queue_front(const queue *);

#endif   //__03QUEUE_H__

编写主函数:03main.c

#include <stdio.h>

#include "03queue.h"

int main() {

    queueque = {0};

   queue_init(&que);

   queue_push(&que, 10);

   queue_push(&que, 20);

   queue_push(&que, 30);

   queue_push(&que, 40);

   queue_push(&que, 50);

   queue_push(&que, 60);

   printf("数字个数是%d\n", queue_size(&que));

   printf("%d\n", queue_pop(&que));

   printf("%d\n", queue_pop(&que));

   printf("%d\n", queue_pop(&que));

   printf("判断满的结果是%d\n", queue_full(&que));

   if (!queue_full(&que)) {

       queue_push(&que, 70);

       queue_push(&que, 80);

       printf("%d\n", queue_pop(&que));

       printf("%d\n", queue_pop(&que));

    }

   printf("%d\n", queue_pop(&que));

   printf("%d\n", queue_pop(&que));

   printf("%d\n", queue_pop(&que));

   printf("判断空的结果是%d\n", queue_empty(&que));

   queue_deinit(&que);

   return 0;

}

 

链表

链表也是一种数据结构,它用来对链式物理结构进行管理

链表用来把链式物理结构的管理代码和其它代码分隔开

链表的功能主要包含插入、删除、查找和遍历

单向链表

链表一般用链式物理结构

编写源文件:04link.c

#include<stdlib.h>

#include"04link.h"

//初始化函数

void link_init(link*p_link) {

    p_link->head.p_next =&(p_link->tail);

    p_link->tail.p_next = NULL;

}

//清理函数

void link_deinit(link*p_link) {

    while (p_link->head.p_next !=&(p_link->tail)) {

        node *p_first = &(p_link->head);

        node *p_mid = p_first->p_next;

        node *p_last = p_mid->p_next;

        p_first->p_next = p_last;

        free(p_mid);

        p_mid = NULL;

    }

}

//获得有效数字个数的函数

int link_size(constlink *p_link) {

    int cnt = 0;

    const node *p_node = NULL;

    for (p_node = &(p_link->head);p_node!= &(p_link->tail);p_node = p_node->p_next) {

        const node *p_first = p_node;

        const node *p_mid = p_first->p_next;

        const node *p_last = p_mid->p_next;

        if (p_mid != &(p_link->tail)) {

            cnt++;

        }

    }

    return cnt;

}

//在链表头加入数字

void link_add_head(link*p_link, int num) {

    node*p_first = NULL, *p_mid = NULL, *p_last = NULL;

    node *p_tmp = (node *)malloc(sizeof(node));

    if (!p_tmp) {

        return ;

    }

    p_tmp->num = num;

    p_tmp->p_next = NULL;

    p_first = &(p_link->head);

    p_mid = p_first->p_next;

    p_last = p_mid->p_next;

    p_first->p_next = p_tmp;

    p_tmp->p_next = p_mid;

}

//在链表末尾追加数字

void link_append(link*p_link, int num) {

    node *p_tmp = (node *)malloc(sizeof(node));

    node *p_node = NULL;

    if (!p_tmp) {

        return ;

    }

    p_tmp->num = num;

    p_tmp->p_next = NULL;

    for (p_node = &(p_link->head);p_node!= &(p_link->tail);p_node = p_node->p_next) {

        node *p_first = p_node;

        node *p_mid = p_first->p_next;

        node *p_last = p_mid->p_next;

        if (p_mid == &(p_link->tail)) {

            p_first->p_next = p_tmp;

            p_tmp->p_next = p_mid;

            break;

        }

    }

}

//按顺序加入数字的函数

voidlink_insert_in_order(link *p_link, int num) {

    node *p_node = NULL;

    node *p_tmp = (node *)malloc(sizeof(node));

    if (!p_tmp) {

        return ;

    }

    p_tmp->num = num;

    p_tmp->p_next = NULL;

    for (p_node = &(p_link->head);p_node!= &(p_link->tail);p_node = p_node->p_next) {

        node *p_first = p_node;

        node *p_mid = p_first->p_next;

        node *p_last = p_mid->p_next;

        if (p_mid == &(p_link->tail) ||p_mid->num > num) {

            p_first->p_next = p_tmp;

            p_tmp->p_next = p_mid;

            break;

        }

    }

}

//删除最前边数字的函数

voidlink_remove_head(link *p_link) {

    node *p_first = NULL, *p_mid = NULL,*p_last = NULL;

    p_first = &(p_link->head);

    p_mid = p_first->p_next;

    p_last = p_mid->p_next;

    p_first->p_next = p_last;

    free(p_mid);

    p_mid = NULL;

}

//删除最后一个结点的函数

voidlink_remove_tail(link *p_link) {

    node *p_node = NULL;

    for (p_node = &(p_link->head);p_node!= &(p_link->tail);p_node = p_node->p_next) {

        node *p_first = p_node;

        node *p_mid = p_first->p_next;

        node *p_last = p_mid->p_next;

        if (p_last == &(p_link->tail)) {

            p_first->p_next = p_last;

            free(p_mid);

            p_mid = NULL;

            break;

        }

    }

}

//获得最前面数字的函数

int link_get_head(constlink *p_link, int *p_num) {

    if (p_link->head.p_next ==&(p_link->tail)) {

        return 0;

    }

    else {

        *p_num =p_link->head.p_next->num;

        return 1;

    }

}

//获得最后一个数字的函数

int link_get_tail(link*p_link, int *p_num) {

    node *p_node = NULL;

    for (p_node = &(p_link->head);p_node!= &(p_link->tail);p_node = p_node->p_next) {

        node *p_first = p_node;

        node *p_mid = p_first->p_next;

        node *p_last = p_mid->p_next;

        if (p_last == &(p_link->tail)) {

            *p_num = p_mid->num;

            return 1;

        }

    }

    return 0;

}

改写头文件:04link.h

#ifndef   __04LINK_H__

#define   __04LINK_H__

typedef struct node {

   int num;

   struct node *p_next;

} node;

typedef struct {

   node head, tail;

} link;

//初始化函数

void link_init(link *);

//清理函数

void link_deinit(link *);

//获得有效数字个数的函数

int link_size(const link *);

//在链表头加入数字

void link_add_head(link *, int );

//在链表末尾追加数字

void link_append(link *, int );

//按顺序加入数字的函数

void link_insert_in_order(link *, int );

//删除最前边数字的函数

void link_remove_head(link *);

//删除最后一个结点的函数

void link_remove_tail(link *);

//获得最前面数字的函数

int link_get_head(const link *, int *);

//获得最后一个数字的函数

int link_get_tail(link *, int *);

#endif  //__04LINK_H__

编写主函数:04main.c

#include <stdio.h>

#include "04link.h"

int main() {

   int num = 0;

   node *p_node = NULL;

   link lnk = {0};

   link_init(&lnk);

   link_add_head(&lnk, 10);

   link_append(&lnk, 100);

   link_insert_in_order(&lnk, 70);

   link_insert_in_order(&lnk, 20);

   link_insert_in_order(&lnk, 40);

   link_insert_in_order(&lnk, 30);

   link_insert_in_order(&lnk, 50);

   printf("数字个数是%d\n", link_size(&lnk));

   for (p_node = &(lnk.head);p_node != &(lnk.tail);p_node =p_node->p_next) {

       node *p_first = p_node;

       node *p_mid = p_first->p_next;

       node *p_last = p_mid->p_next;

       if (p_mid != &(lnk.tail)) {

           printf("%d ", p_mid->num);

       }

    }

   printf("\n");

   link_remove_head(&lnk);

   link_remove_tail(&lnk);

   link_get_head(&lnk, &num);

   printf("最前边的数字是%d\n", num);

   link_get_tail(&lnk, &num);

   printf("最后边的数字是%d\n", num);

   printf("数字个数是%d\n", link_size(&lnk));

   for (p_node = &(lnk.head);p_node != &(lnk.tail);p_node =p_node->p_next) {

       node *p_first = p_node;

       node *p_mid = p_first->p_next;

       node *p_last = p_mid->p_next;

       if (p_mid != &(lnk.tail)) {

           printf("%d ", p_mid->num);

       }

    }

   printf("\n");

   link_deinit(&lnk);

   return 0;

}

目前还不完整,(遍历打印不能写在主函数里),明天继续改造

 

 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值