目录
03队列实现原理
先进先出
0 |
1 |
2 |
3 |
4 |
... |
n |
a1 |
a2 |
a3 |
a4 |
a5 |
定义两个指针 head 与 tail
头head:终是指向头元素位置
尾tail:即将放入元素位置
入队列: tail 操纵
出队列 :head 操纵
应用: 排队买票 排货架
03.1顺序队列
顺序队列会遇到一个问题 那就是当有数据出栈的时候 head向后指向 那么前面的数据空间就不能再用了。(专业术语称之为假溢出 )你可能没有存那么多项,可就是存不下了。
为了防止数据的假溢出我们使用循环队列。
03.2循环队列
入队列由tail 操纵 当tail到达了未元素再入队列 tail就需要移到第一个元素位置 当然也有一个前提队列未满 得有空间让你入队列
queue[tail] = c;
tail = (tail + 1) % SIZE;
判断队列是否已满 牺牲一个数据空间
return (tail + 1) % SIZE == head;
出队列 有head 操纵 当head到达了未元素再出队列 head就需要移到第一个元素位置 当然也有一个前提队列不为空
ch = queue[head];
head = (head + 1) % SIZE;
判断队列为不为空 ——如果head == tail就是队列取完了 为空了
具体代码实现
#include <stdio.h>
#define SIZE 512
char queue[SIZE];
int head = 0, tail = 0;
void enqueue(char c);
char dequeue(void);
int is_empty(void);
int is_full(void);
int main(void)
{
char c = 'A';
int i;
for(i = 0; i < 3; i++)
{
if(!is_full())
{
enqueue(c);
c++;
}
}
while(!is_empty())
{
putchar(dequeue());
}
printf("\n");
return 0;
}
void enqueue(char c)
{
queue[tail] = c;
tail = (tail + 1) % SIZE;
}
char dequeue(void)
{
char ch;
ch = queue[head];
head = (head + 1) % SIZE;
return ch;
}
int is_empty(void)
{
return head == tail;
}
int is_full(void)
{
return (tail + 1) % SIZE == head;
}
03.3双端队列
在循环队列中 入队列是尾入(tail) 出队列是头出(head)那么能不能这样的设计
tail 和 head 既可以入队列也可以出队列!
双端循环队列
head端出队列
c = queue[head]
head = (head+1)%SIZE;
head端入队列
(head-1+SIZE)%SIZE;
queue[head]=b
tail端出队列
tail = (tail-1+size)%size;
c = queue[tail];
tail端入队列
queue[tail] = c;
tail = (tail+1)%size;
队列是否为空
head == tail
队列是否为满:
(tail+1)%size == head;
代码实现
#include <stdio.h>
#include <string.h>
#define SIZE 512
char queue[SIZE];
int head = 0, tail = 0;
void tail_enqueue(char c);
char tai_dequeue(void);
void head_enqueue(char c);
char head_dequeue(void);
int is_empty(void);
int is_full(void);
int is_palindrom(char *pt);
int main(void)
{
char str[100];
printf("Please enter a string:");
gets(str);
if(is_palindrom(str))
printf("str is a palindrom\n");
else
printf("str is not a palindrom\n");
return 0;
}
void tail_enqueue(char c)
{
queue[tail] = c;
tail = (tail + 1) % SIZE;
}
char tail_dequeue(void)
{
tail = (tail - 1 + SIZE) % SIZE;
return queue[tail];
}
void head_enqueue(char c)
{
head = (head - 1 + SIZE) % SIZE;
queue[head] = c;
}
char head_dequeue(void)
{
char ch;
ch = queue[head];
head = (head + 1) % SIZE;
return ch;
}
int is_empty(void)
{
return head == tail;
}
int is_full(void)
{
return (tail + 1) % SIZE == head;
}
int is_palindrom(char *pt)
{
int i, len;
len = strlen(pt);
char c1, c2;
for(i = 0; i < len; i++)
if(!is_full())
tail_enqueue(pt[i]);
while(!is_empty())
{
c1 = head_dequeue();
if(!is_empty())
c2 = tail_dequeue();
else
break;
if(c1 == c2)
continue;
else
return 0;
}
return 1;
}
04队列的实际应用
04.1解码
已知一个数列组合是经过加密后的一串数字,那么现在知道这串加密后的数字,并且知道如何破解的方法,求加密前数字的组合是什么。破解的方法:首先将第1个数删除,紧接着将第2个数放到这串数的末尾,再将第3个数删除并将第4个数放到这串数的末尾,再将 第5个数删除……直到剩下最后一个数,将最后一个数也删除。按照刚才删 除的顺序,把这些删除的数连在一起就是原始的数据。
我们用循环队列实现
#include <stdio.h>
#include <string.h>
#define SIZE 512
char queue[SIZE];
int head = 0, tail = 0;
void enqueue(char c);
char dequeue(void);
int is_empty(void);
int is_full(void);
int main(void)
{
char code[10];
int n;
int i = 0;
char num;
printf("Please enter a code:");
gets(code);
for(n = 0; n < strlen(code); n++)
{
if(!is_full())
enqueue(code[n]);
}
while(!is_empty())
{
code[i++] = dequeue();
if(!is_empty())
{
num = dequeue();
if(!is_full())
enqueue(num);
}
}
printf("Orignal code is :");
for(i = 0; i < strlen(code); i++)
printf("%c", code[i]);
printf("\n");
return 0;
}
void enqueue(char c)
{
queue[tail] = c;
tail = (tail + 1) % SIZE;
}
char dequeue(void)
{
char ch;
ch = queue[head];
head = (head + 1) % SIZE;
return ch;
}
int is_empty(void)
{
return head == tail;
}
int is_full(void)
{
return (tail + 1) % SIZE == head;
}