堆栈、队列、树应该是三种经典抽象数据类型,下面介绍一下队列,队列是一种先进先出的结构,就像食堂排队一样,最先排的人最先打到饭,新入队的人排在队伍的最后,画了一个简单的图,如果用数组来模拟堆栈和队列,堆栈和队列的插入/删除跟图中一样
可以看出,如果用堆栈用数组来表示,那么堆栈只需要维护一个栈顶的元素的下标值(即数组尾部值的下标值)就行,数据想要插入数组,只要数组还有空余,就在数组尾部添加值,并且尾部的序号加一即可。
而队列则困难许多,因为队列是先进先出,需要维护两个序号,一个指向队列的队头(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
#include
#include
#include
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
#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
#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
#include
#include
#include
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
#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
#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 !