lsfreeing 2020-01-24
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERR 2
#define TRUE 1
#define FALSE 0
typedef int status; //定义函数返回的状态,OK & ERR
typedef char datatype; //定义队列中每个元素的数据类型,这里暂定为字符型
typedef struct LinkQueue_anon{
datatype data; //数据区
struct LinkQueue_anon * next; //指针区
} LinkQueue;
typedef struct {
LinkQueue * front, * rear;
/*
创建队列的游标,保存着队列的头尾指针所指向的结点
front指向队列的第一个结点(队头),rear指向队列的最后一个结点(队尾)
规定:
当front=rear=NULL时,表示队列为空
当front=rear!=NULL时,表示队列只有一个元素
*/
}LinkQueueCursor;
/* 函数原型,队列的基本操作,与栈相同 */
LinkQueueCursor *createLinkQueue(datatype first_node_value);
status isEmpty(LinkQueueCursor *L);
void clear(LinkQueueCursor *L);
datatype getTop(LinkQueueCursor *L);
int getLength(LinkQueueCursor *L);
status push(LinkQueueCursor *L, datatype node_to_push);
datatype pop(LinkQueueCursor *L);
void showQueue(LinkQueueCursor *L);
int main(){
/* 测试 */
LinkQueueCursor * mycursor;
mycursor=createLinkQueue(‘1‘); //创建一个游标,同时入队一个元素,其值为‘1‘
printf("isEmpty = %d\n",isEmpty(mycursor));
printf("Length = %d\n",getLength(mycursor));
push(mycursor,‘a‘);
push(mycursor,‘b‘);
push(mycursor,‘c‘);
push(mycursor,‘d‘);
printf("isEmpty = %d\n",isEmpty(mycursor));
printf("Length = %d\n",getLength(mycursor));
showQueue(mycursor);
putchar(‘\n‘);
printf("pop = %c\n",pop(mycursor));
printf("pop = %c\n",pop(mycursor));
printf("getTop = %c\n",getTop(mycursor));
printf("isEmpty = %d\n",isEmpty(mycursor));
printf("Length = %d\n",getLength(mycursor));
showQueue(mycursor);
putchar(‘\n‘);
clear(mycursor);
printf("isEmpty = %d\n",isEmpty(mycursor));
printf("Length = %d\n",getLength(mycursor));
return 0;
}
LinkQueueCursor *createLinkQueue(datatype first_node_value){
LinkQueueCursor *tmp_cur;
LinkQueue *tmp;
tmp_cur=malloc(sizeof(LinkQueueCursor)); //void*类型指针能自动转为其他类型的指针
tmp=malloc(sizeof(LinkQueue));
tmp_cur->front=tmp_cur->rear=tmp; //初始化游标
tmp->data=first_node_value; //初始化数据区
tmp->next=NULL; //初始化指针区
return tmp_cur;
}
status isEmpty(LinkQueueCursor *L){
if (L->front==L->rear && L->front==NULL)
return TRUE;
else
return FALSE;
}
void clear(LinkQueueCursor *L){
LinkQueue * p,* q;
if (isEmpty(L)) return; //空队列,不需要clear,所以直接返回
if (L->front==L->rear && L->front!=NULL){ //只有一个元素的队列,front和rear都指向这个元素
free(L->front);
L->front=L->rear=NULL; //把队列设为空
return;
}
/* 当队列的元素大于1时 */
p=L->front; //p指向当前要被删除的结点
while (p){
//当p不为NULL继续循环
q=p->next; //q指向p的下一个结点
free(p);
p=q; //交换
}
L->front=L->rear=NULL; //把队列设为空
}
datatype getTop(LinkQueueCursor *L){
return L->front->data; //直接返回队头的数据即可
}
int getLength(LinkQueueCursor *L){
int i=0;
LinkQueue * p;
if (isEmpty(L)) return 0; //空队列,返回0
if (L->front==L->rear && L->front!=NULL) return 1; //规定:front=rear,说明队列只有一个元素
/* 队列的长度大于1时 */
p=L->front;
while (p!=L->rear){ //还没到rear(队尾)则继续循环
i++; p=p->next;
}
return i+1;
/*
上面的【队列的长度大于1时】还能用下面的等价代码代替
p=L->front;
while (p){ //p不为NULL则继续循环,因为rear(队尾)结点的next(指针区)一定是NULL
i++; p=p->next;
}
return i;
*/
}
status push(LinkQueueCursor *L, datatype node_to_push){
//node_to_insert表示想要在队尾处入队的元素
LinkQueue * s=malloc(sizeof(LinkQueue));
s->data=node_to_push; //初始化新入队的元素
s->next=NULL;
if (isEmpty(L)==TRUE){
//插入到空队列
L->front=L->rear=s; //入队,当队列只有一个元素时,规定front和rear都指向这个元素
}else{
//插入到已存在元素的队列
L->rear->next=s; //入队,将新元素附在rear指向的结点的后面
L->rear=s; //rear后移,即将它指向新元素
}
return OK;
}
datatype pop(LinkQueueCursor *L){
//出队,即将队头删除
datatype v;
LinkQueue * s;
if (isEmpty(L)) return (datatype)ERR; //空队列
if (L->front==L->rear && L->front!=NULL){ //队列只有一个元素
v=L->front->data; //把这个元素的值赋值给临时变量
free(L->front); //删除这个元素
L->front=L->rear=NULL; //把队列设置为空
}else{
v=L->front->data; //将要删除的元素的值先赋值给临时变量
s=L->front; //将要删除的元素先赋值给临时变量
L->front=L->front->next; //将游标所保存的front后移到下个结点(元素)
free(s); //删除原来的头结点(元素)
}
return v; //返回出队结点(元素)的值
}
void showQueue(LinkQueueCursor *L){
int i;
int total=getLength(L);
LinkQueue * p;
p=L->front;
for (i=0; i<total; i++){
printf("%c\t",p->data); p=p->next;
}
}
/*
队列的定义:只允许在一端进行插入,另一端进行删除的线性表,也是一种操作受限的线性表
一般,把允许插入的一端叫做队尾,允许删除的一端叫做队头
不含任何元素的队列就是空队
所以,队列又称先进先出(First in First out)的线性表
队列的链式存储其实就是线性表中的单链表,只不过它只能尾进头出
*/
/* 环境: Code::Blocks with GCC 5.1 */运行截图:
