栈和队列也是一种线性结构。它们也都用于存储逻辑关系为 "一对一" 的数据,但由于它们比较特殊,因此将其单独作为一章,做重点讲解。
栈是一种基于先进后出(FILO)或者后进先出(LIFO)的数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。
我们称数据进入到栈的动作为压栈(入栈),数据从栈中出去的动作为弹栈(出栈)。
顺序栈:使用数组实现
链式栈:使用链表实现
在实现顺序栈之前,我们先来看一看对于顺序栈的操作:
顺序栈可以使用一维数组实现,base指针指向栈底(数组的第0个元素),top指针是动态的,每次都指向栈顶元素(最后一个放入栈中的元素),因此,我们将base指针称之为:栈底指针,将top指针称之为栈顶指针。
1、顺序栈的描述结构体
#define STACK_INIT_LEN 100
#define STACKINCREMENT 10
typedef struct SqStack{
ElemType *top; //栈顶指针
ElemType *base;
uint stackLen;
}SqStack;
2、顺序栈的初始化
/*
* @brief 初始化一个顺序栈
* @param 初始顺序栈的长度
* @return 返回初始化后的栈的指针
* */
SqStack *stack_init(uint size)
{
//创建一个栈
SqStack *s = (SqStack *)malloc(sizeof(SqStack));
//为栈分配空间
s->base = (ElemType *)malloc(size*sizeof(ElemType));
s->top = s->base;
s->stackLen = size;
s->len = 0;
return s;
}
3、对顺序栈进行扩容
/*
* @brief 对栈进行扩容
* @param s 需要扩容的栈指针
* @return 成功返回TRUE, 失败返回FALSE
*/
int expand(SqStack *s){
printf("[%s %d] stack expand ...\n", __FUNCTION__ , __LINE__);
if (NULL == s)
{
printf("[%s %d] stack pointer is NULL ...\n", __FUNCTION__ , __LINE__);
return FALSE;
}
//为栈重新分配空间,栈底指针指向新的分配好的空间
s->base = (ElemType *)realloc(s->base, (s->stackLen+STACKINCREMENT)*sizeof(ElemType));
//栈顶指针指向新的栈顶元素
s->top = s->base + s->stackLen;
s->stackLen += STACKINCREMENT;
return TRUE;
}
4、入栈
/*
* @brief 入栈
* @param s 栈指针
* @param data 需要入栈的元素
* @return 成功返回TRUE, 失败返回FALSE
* */
int push(SqStack *s, ElemType data){
if (NULL == s)
{
printf("[%s %d] stack pointer is NULL ...\n", __FUNCTION__ , __LINE__);
return FALSE;
}
//如果栈满了
if (s->top - s->base >= s->stackLen)
expand(s);
*(s->top) = data;
s->top++;
return TRUE;
}
5、出栈
/*
* @brief 出栈
* @param s 栈指针
* @param data 存放栈顶元素的指针
* @return 成功返回TRUE, 失败返回FALSE
* */
int pop(SqStack *s, ElemType *data){
if (NULL == s || NULL == data)
return FALSE;
//如果栈为空
if (s->top == s->base)
{
printf("[%s %d] stack is empty ...\n", __FUNCTION__ , __LINE__);
return FALSE;
}
s->top--;
*data = *(s->top);
return TRUE;
}
6、获取栈顶元素
/*
* @brief 获得栈顶元素
* @param s 栈指针
* @param data 存放栈顶元素的指针
* @return 成功返回TRUE, 失败返回FALSE
* */
int get_top_elem(SqStack *s, ElemType *data){
if (NULL == s || NULL == data)
return FALSE;
//如果栈为空
if (s->top == s->base)
{
printf("[%s %d] stack is empty ...\n", __FUNCTION__ , __LINE__);
return FALSE;
}
*data = *(s->top - 1);
return TRUE;
}
7、求顺序栈的长度
int get_len(SqStack s){
if (NULL==s)
return 0;
return s->top-s->base;
}
8、清空顺序栈
/*
* @brief 清除一个栈
* @param s 栈指针
* @return 成功返回TRUE, 失败返回FALSE
* */
int stack_clear(SqStack *s){
if (NULL == s)
{
printf("[%s %d] stack pointer is NULL ...\n");
return FALSE;
}
s->top = s->base;
return TRUE;
}
9、销毁顺序栈
/*
* @brief 销毁栈
* @param s 栈指针
* @return 成功返回TRUE, 失败返回FALSE
* */
int stack_destroy(SqStack *s){
if (NULL == s){
printf("[%s %d] stack pointer is NULL ...\n");
return FALSE;
}
if (s->base != NULL){
free(s->base);
s->top = s->base = NULL;
s->stackLen = 0;
}
return TRUE;
}
链式栈 就是使用链表的方式实现的栈,为了实现先进后出(FILO),我们可以采用链表中的“头插法”实现一个链式栈。
但是与之前所学的链表不同的是:链式栈中不需要头结点(数据域为空的结点)。如上图所示,指向链表中的第一个结点的指针就是栈顶指针,指向链表最后一个结点的指针就是栈底指针。
1、链式栈的描述
typedef struct StackNode{
ElemType data; //数据域
struct StackNode * next; //指针域
}StackNode, *LinkStack;
2、链式栈的初始化
/*
* @brief 初始化一个链式栈
* @return 返回链式栈的栈顶指针
* */
LinkStack stack_init()
{
LinkStack s;
//因为没有头结点,因此初始化链式栈时因为栈为空,所以栈顶指针赋值为NULL
s = NULL;
return s;
}
3、入栈
入栈:链表的头插法,在链表的第一个结点之前插入新的结点
/*
* @brief 入栈
* @param s 栈顶指针的地址
* @param data 需要入栈的元素
* @return 成功返回TRUE,失败返回FALSE
* */
int push(LinkStack *s, ElemType data)
{
if (NULL == s)
return FALSE;
StackNode *p = (StackNode *)malloc(sizeof(StackNode));
p->data = data;
//新的结点的next指向链表的第一个结点(原来的栈顶)
p->next = *s;
//栈顶指针指向新的结点(p变成了链表上的第一个结点)
*s = p;
return TRUE;
}
void print_stack(LinkStack s)
{
if (NULL == s)
return ;
StackNode *t = s;
while (t)
{
printf("%d ", t->data);
t = t->next;
}
printf("\n");
}
4、出栈
/*
* @brief 出栈
* @param s 栈顶指针的地址
* @param data 需要出栈的元素
* @return 成功返回TRUE,失败返回FALSE
* */
int pop(LinkStack *s, ElemType *data){
if (NULL == s || NULL == data || NULL == *s)
return FALSE;
*data = (*s)->data;
StackNode *t = (*s)->next;
free(*s);
*s = t;
return TRUE;
}
5、获取栈顶元素
/*
* @brief 获取栈顶元素
* @param s 栈顶指针
* @param data 需要入栈的元素
* @return 成功返回TRUE,失败返回FALSE
* */
int get_top(LinkStack s, ElemType *data)
{
if (NULL == s || NULL == data)
return FALSE;
*data = s->data;
return TRUE;
}
6、销毁链式栈
/*
* @brief 销毁链式栈
* @param s 栈顶指针的地址
* @return 成功返回TRUE,失败返回FALSE
* */
int stack_destroy(LinkStack *s)
{
if (NULL == s || NULL == *s)
return FALSE;
StackNode *t = *s;;
while (t)
{
t = (*s)->next;
free(*s);
*s = t;
}
//*s = NULL;
return TRUE;
}
1、数值转换
void conversion()
{
LinkStack s = stack_init();
unsigned int num;
printf("plz input A number to be converted : ");
scanf("%d", &num);
unsigned int N;
printf("plz input decimal (2 8 16):");
scanf("%d", &N);
char f;
while (num)
{
if (num % N < 10)
f = num % N + '0';//将一个10以内的整数转换成字符形式:例如 5 -> '5'
else
f = num % N - 10 + 'A';// 10~15转换为 'A' ~ 'F'
push(&s, f);
num = num / N;
}
//出栈
while (is_empty(s) != TRUE)
{
pop(&s, &f);
printf("%c", f);
}
printf("\n");
}
2、括号匹配
假设表达式中允许出现两种括号:圆括号()和方括号[],其嵌套的顺序随意,即( [ ( ) ( ) ] )或者 [ ( [ ] [ ] ) ]等为正确的表达式,但是 ( [ ( ] ) 或者 [ ( [ ) ] 或者 ( [ ( ] ) )等为错误的表达式。检查括号是否匹配可以采用如下逻辑:
遍历整个表达式
如果是左括号入栈
如果是右括号则从栈中出栈一个括号,如果与右括号匹配则继续往后遍历,如果不匹配则说明是错误的表达式
如果表示遍历完毕,最后栈为空说明表达式正确否则说明表达式错误
int brackets_match()
{
char *str = (char *)malloc(100);
LinkStack s = stack_init();
printf("plz input expression: ");
scanf("%s", str);
int i = 0;
char f;
while (str[i] != '\0')
{
if (str[i] == '(' || str[i] == '[')
push(&s, str[i]);
else if (str[i] == ')')
{
pop(&s, &f);
if (f != '(')
return FALSE;
}
else if (str[i] == ']')
{
pop(&s, &f);
if (f != '[')
return FALSE;
}
i++;
}
if (is_empty(s) == TRUE)
return TRUE;
else
return FALSE;
}
3、 表达式求值
需求:输入一个表达式,含加减乘除括号运算,输出表达式的值
例如:求20+(3*400)-100/3的值
逻辑:
使用两个栈,一个 栈存放操作符,一个 栈存放操作数
遍历整个表达式,如果是操作数入栈操作数栈
如果是操作符,则获取操作符栈的栈顶元素,比较两个操作符的优先级,如果比栈顶的操作符优先级低或者相等,则出栈一个操作符,出栈两个操作数,将计算结果入操作数栈
如果比栈顶的操作符优先级高则直接入栈操作符栈
如果遇到的是左括号 ( , 则直接入栈操作符栈
如果是右括号 ),则从操作符栈出栈一个操作符,出栈两个操作数,将计算结果入操作数栈,直到将左括号出栈
#include
#include
#include
#define TRUE 0
#define FALSE -1
#define STACK_INIT_LEN 100
#define STACKINCREMENT 10
typedef unsigned int uint;
typedef int ElemType;
typedef struct SqStack{
ElemType *top; //栈顶指针
ElemType *base; //栈底指针
uint stackLen; //分配的栈的长度
}SqStack;
int is_empty(SqStack *s)
{
if (s->top == s->base)
return TRUE;
return FALSE;
}
/*
* @brief 初始化一个顺序栈
* @param 初始顺序栈的长度
* @return 返回初始化后的栈的指针
* */
SqStack *stack_init(uint size)
{
//创建一个栈
SqStack *s = (SqStack *)malloc(sizeof(SqStack));
//为栈分配空间
s->base = (ElemType *)malloc(size*sizeof(ElemType));
s->top = s->base;
s->stackLen = size;
return s;
}
/*
* @brief 对栈进行扩容
* @param s 需要扩容的栈指针
* @return 成功返回TRUE, 失败返回FALSE
*/
int expand(SqStack *s)
{
printf("[%s %d] stack expand ...\n", __FUNCTION__ , __LINE__);
if (NULL == s)
{
printf("[%s %d] stack pointer is NULL ...\n", __FUNCTION__ , __LINE__);
return FALSE;
}
//为栈重新分配空间,栈底指针指向新的分配好的空间
s->base = (ElemType *)realloc(s->base, (s->stackLen+STACKINCREMENT)*sizeof(ElemType));
//栈顶指针指向新的栈顶元素
s->top = s->base + s->stackLen;
s->stackLen += STACKINCREMENT;
return TRUE;
}
/*
* @brief 入栈
* @param s 栈指针
* @param data 需要入栈的元素
* @return 成功返回TRUE, 失败返回FALSE
* */
int push(SqStack *s, ElemType data)
{
if (NULL == s)
{
printf("[%s %d] stack pointer is NULL ...\n", __FUNCTION__ , __LINE__);
return FALSE;
}
//如果栈满了
if (s->top - s->base >= s->stackLen)
expand(s);
*(s->top) = data;
s->top++;
return TRUE;
}
/*
* @brief 出栈
* @param s 栈指针
* @param data 存放栈顶元素的指针
* @return 成功返回TRUE, 失败返回FALSE
* */
int pop(SqStack *s, ElemType *data)
{
if (NULL == s || NULL == data)
return FALSE;
//如果栈为空
if (s->top == s->base)
{
printf("[%s %d] stack is empty ...\n", __FUNCTION__ , __LINE__);
return FALSE;
}
s->top--;
*data = *(s->top);
return TRUE;
}
/*
* @brief 获得栈顶元素
* @param s 栈指针
* @param data 存放栈顶元素的指针
* @return 成功返回TRUE, 失败返回FALSE
* */
int get_top_elem(SqStack *s, ElemType *data)
{
if (NULL == s || NULL == data)
return FALSE;
//如果栈为空
if (s->top == s->base)
{
printf("[%s %d] stack is empty ...\n", __FUNCTION__ , __LINE__);
return FALSE;
}
*data = *(s->top - 1);
return TRUE;
}
int print_stack(SqStack *s)
{
if (NULL == s)
{
printf("[%s %d] stack pointer is NULL ...\n");
return FALSE;
}
ElemType *t = s->top;
t--;
while (t != s->base)
{
printf("%d ", *t);
t--;
}
printf("%d \n", *t);
return TRUE;
}
/*
* @brief 清除一个栈
* @param s 栈指针
* @return 成功返回TRUE, 失败返回FALSE
* */
int stack_clear(SqStack *s)
{
if (NULL == s)
{
printf("[%s %d] stack pointer is NULL ...\n");
return FALSE;
}
s->top = s->base;
return TRUE;
}
/*
* @brief 销毁栈
* @param s 栈指针
* @return 成功返回TRUE, 失败返回FALSE
* */
int stack_destroy(SqStack *s)
{
if (NULL == s)
{
printf("[%s %d] stack pointer is NULL ...\n");
return FALSE;
}
if (s->base != NULL)
{
free(s->base);
s->top = s->base = 0;
s->stackLen = 0;
}
return TRUE;
}
int cal_oper(int num2, int num1, char f)
{
switch (f) {
case '+':
return num2 + num1;
case '-':
return num2 - num1;
case '*':
return num2 * num1;
case '/':
return num2 / num1;
}
}
int cal_exp(SqStack *oper, SqStack *oprand)
{
//出栈一个操作符
char f;
pop(oper, &f);
//出栈两个操作数
int num1, num2;
pop(oprand, &num1);
pop(oprand, &num2);
int num = cal_oper(num2, num1, f);
return num;
}
int calculate()
{
//操作符栈
SqStack *oper = stack_init(STACK_INIT_LEN);
//操作数栈
SqStack *oprand = stack_init(STACK_INIT_LEN);
char exp[128];
memset(exp, 0, sizeof(exp));
printf("plz input expression: ");
scanf("%s", exp);
int i;
char f;
int num;
while (exp[i] != '\0') {
//如果是数字则计算出该数字后直接入栈
if (exp[i] >= '0' && exp[i] <= '9') {
int num = 0;
while (exp[i] >= '0' && exp[i] <= '9') {
num = num * 10 + (exp[i] - '0'); i++;
}
//将操作数入栈
printf("[%d] push: %d\n", __LINE__, num); push(oprand, num); continue;
}
//如果是左括号 直接入栈
if (exp[i] == '('){ printf("[%d] push: %c\n", __LINE__, exp[i]); push(oper, exp[i]); i++; continue; }
//如果是右括号 从操作符栈出栈一个操作符,从操作数栈出栈两个操作数,计算后将结果入栈操作数栈
if (exp[i] == ')'){
while (is_empty(oper) != TRUE){
get_top_elem(oper, &f);
if (f != '('){
//从操作符栈出栈一个操作符,从操作数栈出栈两个操作数,计算后将结果入栈操作数栈
push(oprand, cal_exp(oper, oprand));
continue;
}
else{
pop(oper, &f);
break;
}
}
i++; continue;
}
//如果是+ -
if (exp[i]=='+' || exp[i]=='-'){
//如果操作符栈为空直接入栈
if (is_empty(oper)==TRUE) {
printf("[%d] push: %c\n", __LINE__, exp[i]);
push(oper, exp[i]); i++; continue;
}
while (is_empty(oper) != TRUE){//一直出栈操作符栈中的符号直到遇到(或者操作符栈为空
// 先获取操作符栈顶元素,如果是左括号直接入栈
get_top_elem(oper, &f);
if (f=='(') { break;}
//从操作符栈出栈一个操作符,从操作数栈出栈两个操作数,计算后将结果入栈操作数栈
push(oprand,cal_exp(oper, oprand));
continue;
}
//最后将遍历到的符号入栈操作符栈
printf("[%d] push: %c\n", __LINE__, exp[i]);
push(oper, exp[i]); i++; continue;
}
//如果是 * /
if (exp[i]=='*' || exp[i]=='/'){
//如果操作符栈为空直接入栈
if (is_empty(oper)==TRUE) {
printf("[%d] push: %c\n", __LINE__, exp[i]);
push(oper, exp[i]); i++; continue;
}
while (is_empty(oper) != TRUE) {//一直出栈操作符栈中的符号直到遇到(或者操作符栈为空,或者+ -
// 先获取操作符栈顶元素,如果是左括号 或者+ - 直接入栈
get_top_elem(oper, &f);
if (f == '(' || f == '+' || f == '-') {break;}
//从操作符栈出栈一个操作符,从操作数栈出栈两个操作数,计算后将结果入栈操作数栈
push(oprand,cal_exp(oper, oprand));
continue;
}
//最后将遍历到的符号入栈操作符栈
printf("[%d] push: %c\n", __LINE__, exp[i]);
push(oper, exp[i]); i++; continue;
}
}
//遍历完整个表达式后将操作符中的元素依次出栈
while (is_empty(oper) != TRUE)
push(oprand,cal_exp(oper, oprand));
pop(oprand,&num);
return num;
}
int main() {
int num;
num = calculate();
printf("%d\n", num);
return 0;
}
//10-5*(3+2)+6/2+10*(4/2)
1、队列的基本概念
队列是一种基先进先出(FIFO)的数据结构,是一种只能在一端进行插入,在另一端进行删除操作的特殊线性表,它按照先进先出的原则存储数据,先进入的数据,在读取数据时先读被读出来。
2、队列的应用
举例1:排队系统的实现
举例2:使用循环队列存储网络摄像头的数据帧(图像数据)
3、队列的具体实现
顺序队列
链队列
在实现顺序队列之前,我们先来看一看对于顺序队列的操作:
顺序队列可以使用一维数组实现,在顺序队列中有两个指针,一个指针front指向队列的队首(数组的第0个元素),一个指针rear指向队列的队尾(最后一个放入队列的元素)。
1、顺序队列的描述
#define QUEUE_INIT_LEN 100
#define QUEUEINCREMENT 10
typedef struct SqQueue
{
ElemType *base; //存储堆上元素的地址空间的首地址
uint front; //队首指针
uint rear; //队尾指针
}SqQueue;
2、关于顺序队列操作的思考
如果对顺序队列进行出队操作,队首指针该如何移动?
队首指针往后移动
对顺序队列进行出队操作后,被出队的元素所占用的空间怎处理?
只能暂时空着,等待下次循环使用
如何判断顺序队列是否为满,是否为空呢?
判断队列为满和空的依据都是front == rear,因此会有冲突
如何判断队列是否溢出呢?
当front为0,rear等于队列最大长度时为真溢出
当front不为0,rear等于队列最大长度时为假溢出
解决方案:使用循环队列。
3、循环队列的概念
队列上的各个元素逻辑上形成一个圆环状。
如何判断队列是否为满呢?
将队列上的一个位置作为空闲位置
假设队列的长度为M,当 (rear + 1)% M == font时,认为队列为满
4、循环顺序队列的初始化
/*
* @brief 初始化一个顺序队列
* @param len 顺序队列的初始化长度(可以存储的元素的最大个数)
* @return 返回初始化的顺序队列
* */
SqQueue SqQueue_init(uint len)
{
SqQueue s;
s.base = (ElemType*)malloc(len*sizeof(ElemType));
s.front = 0;
s.rear = 0;
return s;
}
5、获取顺序队列的长度(实际存储的元素的个数)
/*
* @brief 获取顺序队列的长度
* @param s 顺序队列
* @return 顺序队列的长度
* */
int SqQueue_length(SqQueue s)
{
return s.rear - s.front;
}
6、判断顺序队列是否为空
/*
* @brief 判断顺序队列是否为空
* @param 顺序队列
* @return 为空返回TRUE,不为空返回FALSE
* */
int is_empty(SqQueue s)
{
if (s.front == s.rear)
return TRUE;
else
return FALSE;
}
7、判断顺序队列是否为满
/*
* @brief 判断顺序队列是否为满
* @param 顺序队列
* @return 为满返回TRUE,不为满返回FALSE
* */
int is_full(SqQueue s)
{
if ((s.rear+1)%QUEUE_INIT_LEN == s.front)
return TRUE;
else
return FALSE;
}
8、入队
/*
* @brief 循环顺序队列入队
* @param data 需要入队得元素
* @return 成功返回TRUE, 失败返回FALSE
* */
int EnQueue(SqQueue *s, ElemType data)
{
if (NULL == s)
return FALSE;
if (is_full(*s) == TRUE)
{
printf("[%s %d] queue is full ...\n", __FUNCTION__ , __LINE__);
return FALSE;
}
s->base[s->rear] = data;
s->rear= (s->rear + 1) % QUEUE_INIT_LEN; //尾指针往后移动
return TRUE;
}
9、顺序队列打印
/*
* @brief 输出顺序队列中的元素
* @param s 需要输出顺序队列
* @return 成功返回TRUE,失败返回FALSE
* */
int print_SqQueue(SqQueue s)
{
if (is_empty(s) == TRUE)
{
printf("[%s %d] SqQueue is empty\n", __FUNCTION__ , __LINE__);
return FALSE;
}
int i = s.front;
while (i != s.rear)
{
printf("%d ", s.base[i]);
//i 指向下一个位置
i = (i+1)%QUEUE_INIT_LEN;
}
printf("\n");
return TRUE;
}
10、出队
/*
* @brief 循环顺序队列出队
* @param data 存储出队元素的指针
* @return 成功返回TRUE, 失败返回FALSE
* */
int DeQueue(SqQueue *s, ElemType *data)
{
if (NULL == s)
return FALSE;
if (is_empty(*s) == TRUE)
{
printf("[%s %d] queue is empty ...\n", __FUNCTION__ , __LINE__);
return FALSE;
}
*data = s->base[s->front];
s->front = (s->front + 1) % QUEUE_INIT_LEN; //队首指针往后移动
return TRUE;
}
链式队列 可以理解为对单向链表的操作,入队就是单向链表的尾插法,出队则需要销毁第一个数据结点(类似删除链表上的第一个数据结点)。
#include
#include
#define TRUE 0
#define FALSE -1
typedef int ElemType;
typedef unsigned int uint;
/*
* 链式队列可以理解成一个通过尾插法创建的链表(可以带头结点也可以不带头结点)
* */
//定义链表上的一个结点
typedef struct LNode
{
ElemType data; //数据域
struct LNode *next; //指向当前结点的下一个结点的指针(这个指针保存了下一个结点的存储位置)
}LNode;
//定义一个结构体描述一个链式队列
typedef struct LinkQueue
{
LNode *front; //队首指针
LNode *rear; //队尾指针
}LinkQueue;
/*
* @brief 初始化一个链式队列
* @return 代表链式队列的结构体
* */
LinkQueue queue_init()
{
//创建一个头结点
LinkQueue L;
//当队列为空时,队首指针和队尾指针都为NULL
L.front = L.rear = NULL;
return L;
}
/*
* @brief 打印链式队列中的元素
* @param L 链式队列结构体
* @return
* */
void print_queue(LinkQueue L)
{
//使用临时指针指向链表上的第一个数据结点(就是头节点的下一个结点)
LNode *tmp;
tmp = L.front;
while (tmp != NULL)
{
printf("%d ", tmp->data);
//让tmp指针指向下一个结点
tmp = tmp->next;
}
printf("\n");
}
/*
* @brief 入队
* @param L 链式队列的指针
* @param data 需要插入的元素
* @return 成功返回TRUE,失败返回FALSE
* */
int EnQueue(LinkQueue *L, ElemType data)
{
if (NULL == L)
return FALSE;
//先创建一个结点
LNode *p = (LNode *)malloc(sizeof(LNode));
p->data = data;
p->next = NULL;
//先判断队列是否为空队列
if (L->front == NULL)
{
L->front = p;
L->rear = p;
return TRUE;
}
//如果队列不为空,那么将rear指向新的结点
L->rear->next = p;
L->rear = p;
return TRUE;
}
int DeQueue(LinkQueue *L, ElemType *data)
{
if (NULL == L || NULL == data)
return FALSE;
if (NULL == L->front)
return FALSE;
//首先保存链式队列上的第一个结点的值
*data = L->front->data;
//使用临时指针执行队首
LNode *t = L->front;
//队首指针指向后一个结点(出队后原来队列上的第二个结点变成了新的队首结点)
L->front = L->front->next;
//删除原来的队首结点
free(t);
return TRUE;
}
int main() {
LinkQueue L;
L = queue_init();
int i;
for (i = 0; i < 10; i++)
EnQueue(&L, i);
print_queue(L);
ElemType data;
while (DeQueue(&L, &data) != FALSE)
printf("%d\n", data);
return 0;
}