线性表之链队列(C语言实现)

一、链队列

1、队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已,我们把它简称为链队列。

2、为了操作上的方便,我们增加一个队头结点,一个队头指针,一个队尾指针。

3、空队列时,front和rear指针都指向头结点,如图所示

4、非空队列时,对头指针指向队头结点,队尾指针指向终端结点,如图所示

二、链队列数据结构 

typedef int QElemType;//QElemType根据实际情况而定,这里假设为int
typedef struct Qnode
{
	QElemType data;
	struct Qnode *next;
}Qnode,*QueuePtr;

typedef struct //队列的链表结构
{
	QueuePtr front,rear;//队头、队尾指针
}LinkQueue,*LinkQueuePtr;

 三、基本操作

1、队列创建

bool CreateQueue(LinkQueue *Q)
{
	if(!Q)
	{
		return false;
	}

	Q->front = Q->rear = (QueuePtr)malloc(sizeof(Qnode));
	if(!Q->front)
	{
		return false;
	}

	Q->front->next = NULL;// 队头节点指向NULL

	return true;
}

2、入队

bool Enqueue(LinkQueue *Q, QElemType e)
{
	QueuePtr s = (QueuePtr)malloc(sizeof(Qnode));
	if(!s)
		return false;

	s->data = e;
	s->next = NULL;

	Q->rear->next = s;//把拥有元素e新结点s赋值给队尾指针的后继
	Q->rear = s;//把当前的s设置为队尾结点,rear指向s

	return true;
}

3、出队

//注意出队分为两种情况
bool Dequeue(LinkQueue *Q, QElemType *e)
{
	QueuePtr p = NULL;

	if(!Q)
		return false;	

	if(Q->front == Q->rear)
		return false;

	p = Q->front->next;
	*e = p->data;
	Q->front->next = p->next;

	if(Q->rear == p)//只有一个结点的情况(不含头结点)
		Q->rear = Q->front;//使尾结点指向头结点

	free(p);

	return true;
}

4、队列是否空

bool QueueEmpty(LinkQueue *Q) {
	if(!Q)
		return false;

    // 头指针和尾指针位置相等,队列为空
    if (Q->front == Q->rear) {
        return true;
    } else {
        return false;
    }
}

 

5、遍历队列

bool visit(QElemType e) {
    printf("%d ", e);
    return true;
}

bool QueueTravel(LinkQueue *Q) {
    QueuePtr p; // 用于遍历队列中的节点
	
	if(!Q)
		return false;

    p = Q->front->next; // p指向头节点

    printf("遍历队列,队中的元素是:\n");
    // 当队列中还有元素
    while (p) {
        visit(p->data); // 打印当前节点的值
        p = p->next; // p移动到队列下一个位置
    }
	printf("\n");
    return true;
}

 

6、获取队列长度

int QueueLength(LinkQueue *Q)
{
	if(!Q)return -1;

	QueuePtr p = Q->front;
	int count = 0;

	while(p->next)
	{
		count++;
		p = p->next;
	}

	return count;
}

7、获取队列头

bool GetHead(LinkQueue *Q, QElemType *e) {
    QueuePtr p;

	if(!Q)
		return false;

    // 队列为空,获取失败
    if (Q->front == Q->rear) {
        return false;
    }

    p = Q->front->next; // p指向队列的第一个元素
    *e = p->data; // 将队列头元素的值赋值给e元素
    return true;
}

8、清空队列

bool ClearQueue(LinkQueue *Q) {
    QueuePtr p, q; // p用来遍历队列节点,q用来指向被删除的节点

	if(!Q)return true;
		printf("空队列\n");

	printf("清空队列\n");
    Q->rear = Q->front; // 队尾指针指向队头指针
    p = Q->front->next; // p指向队头指针的下一个节点
    Q->front->next = NULL; // 队头指针的下一个节点指向NULL(表示删除之后的所有元素)

    // 当队列中还有元素,释放头节点之后的所有节点
    while (p) {
        q = p; // q节点指向被删除节点
        p = p->next; // p指向队列的下一个节点
        free(q); // 释放q节点
    }
    return true;
}

9、销毁队列

bool DestroyQueue(LinkQueue *Q)
{
	if(!Q)return false;

	printf("销毁队列\n");
	while (Q->front) 
	{
        Q->rear = Q->front->next;// 队尾指针指向队头指针的下一个元素
        free(Q->front); // 释放队头指针所在节点
        Q->front = Q->rear; // 队头指针指向队尾指针(即原来的下一个元素)
    }

	return true;
}

四、测试代码 及测试结果

#include<stdio.h>
#include<stdlib.h>
#include"malloc.h"


void main(void)
{	
	LinkQueue Lqueue;
	CreateQueue(&Lqueue);

	QElemType i;
	for(i = 0;i < 10;i++)
	{
		if(false == Enqueue(&Lqueue,i)) break;
		else
			printf("依次入队元素:%d\n",i);
	}
	int len = QueueLength(&Lqueue);
	printf("===========len:%d===========\n",len);
	QueueTravel(&Lqueue);

	QElemType e;

	GetHead(&Lqueue,&e);
	printf("链表头为:%d\n",e);

	for(i = 0;i < 5;i++)
	{
		if(false == Dequeue(&Lqueue,&e)) break;
		else
			printf("依次出队元素:%d\n",e);
	}
	QueueTravel(&Lqueue);

	ClearQueue(&Lqueue);
	QueueEmpty(&Lqueue);

	DestroyQueue(&Lqueue);

	system("pause");
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值