C语言经典抽象数据类型----队列(动态数组队列和链式队列)

堆栈、队列、树应该是三种经典抽象数据类型,下面介绍一下队列,队列是一种先进先出的结构,就像食堂排队一样,最先排的人最先打到饭,新入队的人排在队伍的最后,画了一个简单的图,如果用数组来模拟堆栈和队列,堆栈和队列的插入/删除跟图中一样

可以看出,如果用堆栈用数组来表示,那么堆栈只需要维护一个栈顶的元素的下标值(即数组尾部值的下标值)就行,数据想要插入数组,只要数组还有空余,就在数组尾部添加值,并且尾部的序号加一即可。

而队列则困难许多,因为队列是先进先出,需要维护两个序号,一个指向队列的队头(front),一个指向队列的队尾(rear),这样也会出现一个问题,如左边的图,当数组空间为5,已经存储了10~50数值,又连续删除 三个值,此时虽然数组尚未满,但是尾部已经没有空间了,无法插入新的元素。

而解决方法一种是让删除后,后面的元素往前挪一个位置,但是这种复制元素的开销在大型的队列不可取。

另一种方法是让尾部与首部相接,形成循环的数组,如右图,当60插入之后,位置插入到首部中,而这时候尾部的rear应当变为0,让rear变为0的方法可以按照下面两种方法做,当然对于front也要类似这种技巧

1.rear是每次增加元素都会加1,当加到超过队列的大小时候,让rear为0

2.让rear增加1后的值与队列的大小求余(5%5=0,6%5=1)

eg.1
rear + =1;
if (rear >= QUEUE_SIZE )
    rear = 0;
eg.2
rear = (rear + 1) % QUEUE_SIZE;

而利用循环的数组也会出现一个问题,如右图当连续减至最后一个元素删除,此时循环数组为空,但是队头,队尾的值和队列满的时候的状态一样,解决的方法有两个,一:再添加一个变量记录变量的数目,二:为循环数组多申请一个空间,而这个空间始终不用,这样队列“满”和空的时候就不会出现队头和队尾相同的情况,当然这时候的“满”是指总空间减一的情况。

以下给出简单C语言实现动态分配的队列的代码:

queue.c

#include "queue.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

static size_t queue_size;
static QUEUE_TYTE *queue;
static size_t front = 1;
static size_t rear = 0;

/*create queue*/
void create_queue(size_t size)
{
        assert(queue_size == 0);
        queue_size = size + 1;
        queue = malloc(queue_size * sizeof(QUEUE_TYTE));
        assert(queue != NULL);


}

/*destory queue*/
void destroy_queue(void)
{
        assert(queue_size > 0);
        queue_size = 0;
        free(queue);
}


/*insert*/
void insert(QUEUE_TYTE value)
{
        assert(!is_full());
        rear = (rear + 1) % queue_size;
        memcpy(queue + rear, &value, sizeof(value));

}

/*delete*/
void delete(void)
{
        assert(!is_empty());
        front = (front + 1) % queue_size;

}

/*first*/
QUEUE_TYTE* first(void)
{
        QUEUE_TYTE *temp;
        assert(!is_empty());
        temp = queue + front;
        return temp;
}

/*is_empty*/
int is_empty(void)
{
        return (rear + 1) % queue_size == front;
}

/*is_full*/

int is_full(void)
{
        return (rear + 2) % queue_size == front;
}


queue.h

#include <stdio.h>
#define QUEUE_TYTE CAR
typedef struct car {
        char brand[100];
        char price[100];
} CAR;

void create_queue(size_t size);
void destroy_queue(void);
void insert(QUEUE_TYTE value);
void delete(void);
CAR* first(void);
int is_empty(void);
int is_full(void);

主函数car.c

#include <stdio.h>
#include "queue.h"
CAR cars[] = {
        {"Rolls-Royce","$500K"},
        {"Ferrari","$200K"},
        {"Porsche","$90K"},
        {"Lamborghini","$600K"}
};

int main(void)
{
        int i;
        CAR *car_tmp;
        int length = sizeof(cars)/sizeof(cars[0]);
        create_queue(10);
        for (i = 0; i < length; i++) {
                insert(cars[i]);
                if (i == length -1)
                        printf("%s car | all in!\n",cars[i].brand);
                else
                        printf("%s car >>  ",cars[i].brand);
        }

        for (i = 0; i < length; i++) {
                car_tmp = first();
                if (i == length -1)
                        printf("<< %s car | all out !\n",car_tmp->brand);
                else
                        printf("<< %s car ",car_tmp->brand);
                delete();
        }

        destroy_queue();
 
}               

简单的编译以及结果显示 

gcc car.c queue.c -o car
Rolls-Royce car >>  Ferrari car >>  Porsche car >>  Lamborghini car | all in!
<< Rolls-Royce car << Ferrari car << Porsche car << Lamborghini car | all out !

也用链表的形式实现队列的方法,用链表的形式更为简单,不需要维护队头和队尾两个值

queue_list.c

#include "queue_list.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

typedef struct QUEUE_NODE {
        QUEUE_TYTE value;
        struct QUEUE_NODE *next;
} QUEUE_NODE;

QUEUE_NODE queue;
QUEUE_NODE *QUEUE = &queue;

/*create queue*/
void create_queue(size_t size)
{

}

/*destory queue*/
void destroy_queue(void)
{
        while(!is_empty())
                delete();
}

/*insert*/
void insert(QUEUE_TYTE value)
{
        QUEUE_NODE *new_node;
        QUEUE_NODE *current_node = QUEUE;
        new_node = malloc(sizeof(QUEUE_NODE));
        assert(new_node != NULL);
        while(current_node->next != NULL) {
                current_node = current_node->next;
        }
        memcpy(&new_node->value, &value, sizeof(value));
        new_node->next = NULL;
        current_node->next = new_node;

}

/*delete*/
void delete(void)
{
        QUEUE_NODE *first_node;
        assert(!is_empty());
        first_node = QUEUE->next;
        QUEUE->next = first_node->next;
        free(first_node);

}

/*first*/
QUEUE_TYTE* first(void)
{
        QUEUE_NODE *first_node;
        assert(!is_empty());
        first_node = QUEUE->next;
        return &first_node->value;
}

/*is_empty*/
int is_empty(void)
{
        return QUEUE->next == NULL ? 1 : 0;
}

/*is_full*/
int is_full(void)
{
        return 0;
}

queue_list.h

#include <stdio.h>
#define QUEUE_TYTE CAR
typedef struct car {
        char brand[100];
        char price[100];
} CAR;

void create_queue(size_t size);
void destroy_queue(void);
void insert(QUEUE_TYTE value);
void delete(void);
CAR* first(void);
int is_empty(void);
int is_full(void);

主函数car.c

#include <stdio.h>
#include "queue_list.h"
CAR cars[] = {
        {"Rolls-Royce","$500K"},
        {"Ferrari","$200K"},
        {"Porsche","$90K"},
        {"Lamborghini","$600K"}
};

int main(void)
{
        int i;
        CAR *car_tmp;
        int length = sizeof(cars)/sizeof(cars[0]);
        create_queue(10);
        for (i = 0; i < length; i++) {
                insert(cars[i]);
                if (i == length -1)
                        printf("%s car | all in!\n",cars[i].brand);
                else
                        printf("%s car >>  ",cars[i].brand);
        }


        for (i = 0; i < length; i++) {
                car_tmp = first();
                if (i == length -1)
                        printf("<< %s car | all out !\n",car_tmp->brand);
                else
                        printf("<< %s car ",car_tmp->brand);
                delete();
        }

        destroy_queue();

}


简单的编译以及结果,跟上面的一致

gcc car.c queue_list.c -o car
Rolls-Royce car >>  Ferrari car >>  Porsche car >>  Lamborghini car | all in!
<< Rolls-Royce car << Ferrari car << Porsche car << Lamborghini car | all out !

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

喝醉的鱼

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

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

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

打赏作者

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

抵扣说明:

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

余额充值