zoukankan      html  css  js  c++  java
  • [数据结构

    一、什么是链队列?

    队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已,我们把它简称为链队列。为了操作上的方便,我们将队头指针指向链队列的头结点,而队尾指针指向尾结点,如下图所示:


    空队列时,front和rear都指向头结点,如下图所示。


    链队列的结构为:

    typedef int QElemType; /* QElemType类型根据实际情况而定,这里假设为int */
    
    /* 结点结构 */
    typedef struct QNode 
    {
    	ElemType data;
    	struct QNode *next;
    }QNode;
    
    /* 队列的链表结构 */
    typedef struct			
    {
    	QNode *front; // 队头指针
    	QNode *rear; // 队尾指针
    }LinkQueue;
    

    二、基本操作

    2.1 初始化操作

    实现代码如下:

    // 初始化链队列操作
    Status initQueue(LinkQueue *Q)
    {
    	Q->front = Q->rear = (Node *)malloc(sizeof(Node));
    	if (!Q->front)
    		return FALSE;
    	Q->front->next = NULL;
    
    	return TRUE;
    }
    

    2.1 入队操作

    人队操作时,其实就是在链表尾部插入结点,如下图所示:


    实现代码如下:

    // 入队操作
    Status enQueue(LinkQueue *Q, ElemType e)
    {
    	Node *s = (Node *)malloc(sizeof(Node));
    	if (!s)
    		return FALSE;
    
    	s->data = e;
    	s->next = NULL;
    	Q->rear->next = s;	// 把拥有元素e的新结点s赋值给原队尾结点的后继
    	Q->rear = s; // 把当前的s设置为队尾结点,rear指向s
    
    	return TRUE;
    }
    

    2.3 出队操作

    出队操作时,就是头结点的后继结点出队,将头结点的后继改为它后面的结点,若链表除头结点外只剩一个元素时,则需将rear指向头结点,如下图所示:

    实现代码如下:

    // 出队操作
    Status deQueue(LinkQueue *Q, ElemType *e)
    {
    	Node *p;
    	if (Q->front == Q->rear)
    		return FALSE;
    
    	p = Q->front->next; // 将欲删除的队头结点暂存给p,见图中①
    	*e = p->data; // 将欲删除的队头结点的值赋值给e
    	Q->front->next = p->next; // 将原队头结点的后继p->next赋值给头结点后继,见图中②
    	if (Q->rear == p) // 若队头就是队尾,则删除后将rear指向头结点,见图中③
    		Q->rear = Q->front;
    	free(p);
    
    	return TRUE;
    }
    

    2.4 遍历操作

    实现代码如下:

    // 遍历队列操作
    Status tarverseQueue(const LinkQueue Q)
    {
    	Node *p;
    	p = Q.front->next;
    	while (p)
    	{
    		printf("%d ", p->data);
    		p = p->next;
    	}
    	printf("
    ");
    
    	return TRUE;
    }
    

    三、完整程序

    #include <stdio.h>
    #include <stdlib.h>    
    
    #define TRUE 1
    #define FALSE 0
    #define MAXSIZE 20 /* 存储空间初始分配量 */
    
    typedef int Status;
    typedef int ElemType; /* ElemType类型根据实际情况而定,这里假设为int */
    
    /* 结点结构 */
    typedef struct Node 
    {
    	ElemType data;
    	struct Node *next;
    }Node;
    
    /* 队列的链表结构 */
    typedef struct			
    {
    	Node *front; // 队头指针
    	Node *rear; // 队尾指针
    }LinkQueue;
    
    Status initQueue(LinkQueue *Q); // 初始化链队列操作
    Status enQueue(LinkQueue *Q, ElemType e); // 入队操作
    Status deQueue(LinkQueue *Q, ElemType *e); // 出队操作
    Status tarverseQueue(const LinkQueue Q); // 遍历队列操作
    Status destroyQueue(LinkQueue *Q); // 销毁队列操作
    Status clearQueue(LinkQueue *Q); // 清空队列操作
    Status isEmpty(const LinkQueue Q); // 判断是否为空队列
    Status getHead(const LinkQueue Q, ElemType *e); // 获得队头元素
    int getLength(const LinkQueue Q); // 获得队列的长度
    
    // 初始化链队列操作
    Status initQueue(LinkQueue *Q)
    {
    	Q->front = Q->rear = (Node *)malloc(sizeof(Node));
    	if (!Q->front)
    		return FALSE;
    	Q->front->next = NULL;
    
    	return TRUE;
    }
    
    // 入队操作
    Status enQueue(LinkQueue *Q, ElemType e)
    {
    	Node *s = (Node *)malloc(sizeof(Node));
    	if (!s)
    		return FALSE;
    
    	s->data = e;
    	s->next = NULL;
    	Q->rear->next = s;	// 把拥有元素e的新结点s赋值给原队尾结点的后继,见图中①
    	Q->rear = s; // 把当前的s设置为队尾结点,rear指向s,见图中②
    
    	return TRUE;
    }
    
    // 出队操作
    Status deQueue(LinkQueue *Q, ElemType *e)
    {
    	Node *p;
    	if (Q->front == Q->rear)
    		return FALSE;
    
    	p = Q->front->next; // 将欲删除的队头结点暂存给p,见图中①
    	*e = p->data; // 将欲删除的队头结点的值赋值给e
    	Q->front->next = p->next; // 将原队头结点的后继p->next赋值给头结点后继,见图中②
    	if (Q->rear == p) // 若队头就是队尾,则删除后将rear指向头结点,见图中③
    		Q->rear = Q->front;
    	free(p);
    
    	return TRUE;
    }
    
    // 遍历队列操作
    Status tarverseQueue(const LinkQueue Q)
    {
    	Node *p;
    	p = Q.front->next;
    	while (p)
    	{
    		printf("%d ", p->data);
    		p = p->next;
    	}
    	printf("
    ");
    
    	return TRUE;
    }
    
    // 销毁队列操作
    Status destroyQueue(LinkQueue *Q)
    {
    	while (Q->front)
    	{
    		Q->rear = Q->front->next;
    		free(Q->front);
    		Q->front = Q->rear;
    	}
    
    	return TRUE;
    }
    
    // 清空队列操作
    Status clearQueue(LinkQueue *Q)
    {
    	Node *p;
    	Node *q;
    
    	Q->rear = Q->front;
    	p = Q->front->next;
    	Q->front->next = NULL;
    	while (p)
    	{
    		q = p;
    		p = p->next;
    		free(q);
    	}
    
    	return TRUE;
    }
    
    // 判断是否为空队列
    Status isEmpty(const LinkQueue Q)
    {
    	return Q.front == Q.rear ? TRUE : FALSE;
    }
    
    // 获得队头元素
    Status getHead(const LinkQueue Q, ElemType *e)
    {
    	Node *p;
    	if (Q.front == Q.rear)
    		return FALSE;
    	p = Q.front->next;
    	*e = p->data;
    
    	return TRUE;
    }
    
    // 获得队列的长度
    int getLength(const LinkQueue Q)
    {
    	int i = 0;
    	Node *p;
    	p = Q.front;
    	while (Q.rear != p)
    	{
    		i++;
    		p = p->next;
    	}
    	return i;
    }
    
    int main()
    {
    	LinkQueue Q;
    
    	// 初始化队列
    	initQueue(&Q);
    
    	// 入队操作 
    	for (int i = 0; i < 4; i++)
    		enQueue(&Q, i);
    	printf("入队操作(0、1、2、3)! 
    
    ");
    
    	// 出队操作
    	ElemType d;
    	deQueue(&Q, &d);
    	printf("删除的元素是%d 
    
    ", d);
    
    	// 遍历队列
    	printf("遍历队列: ");
    	tarverseQueue(Q);
    	printf("
    ");
    
    	// 判断是否为空队列
    	printf("现在队列空否? %u (1:空 0:否)
    
    ", isEmpty(Q));
    
    	// 获得队列的长度
    	printf("队列长度为: %d 
    
    ", getLength(Q));
    
    	// 获得队头元素
    	getHead(Q, &d);
    	printf("队头元素是%d 
    
    ", d);
    
    	return 0;
    }
    

    输出结果如下图所示:

    img


    参考:

    《大话数据结构 - 第4章》 栈与队列


  • 相关阅读:
    Another mysql daemon already running with the same unix socket
    cloud maintenance of OpenNebula
    内核分析阅读笔记
    eucalyptus,openNebula云构建漫谈
    quotation
    Adress
    cos
    COS回应7大质疑
    linux内核地址mapping
    开源 免费 java CMS
  • 原文地址:https://www.cnblogs.com/linuxAndMcu/p/10327836.html
Copyright © 2011-2022 走看看