数据结构-队列

 队列 queue 

    1)队列 
        是一种 "先进先出 FIFO"  "后进后出"的线性表 
        它只允许 在表的一端进行插入操作 
                在表的另外一端进行删除操作 

            队尾 rear : 允许插入元素    入队
            队首 front : 允许删除元素   出队


    2)队列的基本操作 


        InitQueue()     初始化一个队列 
        EnQueue()       入队 
        DeQueue()       出队
        QueueLength()   队列的长度(元素的个数)
        GetHead()       获取队首元素,但是不出队
        IsEmpty()       判断队列是否为空
        ClearQueue()    清空队列
        DestroyQueue()  销毁队列 

    
    3)队列的实现 

        (3.1)顺序队列
                用一组地址连续的空间 依次存储队列的每一个元素   "数组"

            "循环队列"

                    #define MAX_LEN 10      //队列的最大的容量
                    typedef int ElemType;   //数据的类型 

                    typedef struct CircleQueue      //循环队列
                    {
                        ElemType data[MAX_LEN];
                        int front;          //保存队首元素的下标
                        int rear;           //保存队尾元素的下标
                        int num;            //保存队列中元素的个数
                    } CircleQueue ;

             

           练习: 
                    1)初始化一个循环队列 

                        CircleQueue.c   /  CircleQueue.h   

//初始化一个循环队列 
CircleQueue * InitQueue()
{
    //创建一个循环队列,并初始化 
    CircleQueue * q = (CircleQueue *)malloc( sizeof(CircleQueue) );
	q->front = -1;
	q->rear = -1;
	q->num = 0;

	return q;
}

                    2)判断队列是否为空 
                        返回值: 
                            1 为空
                            0 不为空

int IsEmpty( CircleQueue * q )
{
    //队列不存在 || 队列的元素个数为0 
    if( q == NULL || q->num == 0 )
    {
		return 1;
    }

    return 0;
}

                    3)获取队列的长度(元素个数)

int QueueLength( CircleQueue * q )
{
	if( q == NULL )
	{
		return 0;
	}

	return q->num;
}

                    4)清空队列

void ClearQueue( CircleQueue * q )
{
	if( q )
	{
		q->front = -1;
		q->rear = -1;
		q->num = 0;
	}
}

                    5)销毁队列 

void DestroyQueue( CircleQueue * q )
{
	if( q )
	{
		q->front = -1;
		q->rear = -1;
		q->num = 0;

		free( q );
	}
}

                    6)入队 
                        返回值:
                            1 入队成功
                            0 入队失败

int EnQueue( CircleQueue *q, ElemType d )
{
    //不能入队的情况: 队列不存在 || 队列满了 
	if( q == NULL || q->num == MAX_LEN )
	{
		return 0;
	}
    
    //入队,只允许在队尾进行入队操作
	if( q->num == 0 )
	{
		q->front = ( q->front + 1 ) % MAX_LEN;
		q->rear = ( q->rear + 1 ) % MAX_LEN;
		q->data[ q->rear ] = d;
	}
	else 
	{
		q->rear = ( q->rear + 1 ) % MAX_LEN;
		q->data[ q->rear ] = d;
	}
    q->num ++;

    return 1;
}

                    7)出队 
                        返回值:
                            1 出队成功
                            0 出队失败

int DeQueue( CircleQueue *q, ElemType *d )
{
    //不能出队的情况: 队列不存在 || 队列为空 
	if( q == NULL || q->num == 0 )
	{
		return 0;
	}
    
    //出队,只允许在队首进行出队操作
	*d = q->data[ q->front ];
	q->num --;

	if( q->num == 0 )
	{
		q->front = ( q->front + 1 ) % MAX_LEN;
		q->rear = ( q->rear + 1 ) % MAX_LEN;
		//q->front = -1;
		//q->rear = -1;
	}
	else 
	{
		q->front = ( q->front + 1 ) % MAX_LEN;
	}

	return 1;    
}

                    8)获取队首元素,但是不出队 (队首下标不变)
                        返回值: 
                            1 获取成功
                            0 获取失败 

int GetHead( CircleQueue *q, ElemType *d )
{
    //不能获取的情况: 队列不存在 || 队列为空 
	if( q == NULL || q->num == 0 )
	{
		return 0;
	}
    
    //获取队首元素的值,下标保持不变
    *d = q->data[ q->front ];

    return 1;
}

        (3.2)链式队列 
                "带头结点的单向链表"

                    typedef int ElemType;   //数据元素中 数据的类型
                    typedef struct node             //数据元素的类型
                    {
                        ElemType data;          //数据域  --> 存储数据 
                        struct node * next;     //指针域  --> 保存逻辑上的关系(下一个)
                    } Node;

                    //队列的头结点的类型 
                    typedef struct LinkQueue    //链式队列 
                    {
                        Node * front;   //指向队首元素 first
                        Node * rear;    //指向队尾元素 last
                        int num;        //保存队列的数据元素的个数
                        //... 
                    } LinkQueue ;

             

                  基本操作: 同上


                    练习: 
                        LinkQueue.c  / LinkQueue.h  

                        1)初始化一个链式队列

LinkQueue * InitQueue()
{
    //创建队列的头结点,并初始化 
	LinkQueue *q = (LinkQueue *)malloc( sizeof(LinkQueue) );
	q->front = NULL;
	q->rear = NULL;
	q->num = 0;

    return q;
}

                        2)判断队列是否为空 

int IsEmpty( LinkQueue * q )
{
    //队列不存在 || 队列的元素个数为0
    if( q == NULL || q->num == 0 )
    {
		return 1;
    }

    return 0;
}

                        3)获取队列的长度 

int QueueLength( LinkQueue * q )
{
	if( q == NULL )
	{
		return 0;
	}

	return q->num;
}

                        4)清空队列 

void ClearQueue( LinkQueue * q )
{
    //队列不存在 || 队列的元素个数为0 
    if( q == NULL || q->num == 0 )
    {
		return ;
    }

    //遍历,删除每一个数据节点 (只允许在队首进行出队操作-->删除队首节点)
	Node * p = q->front;	//遍历指针

	while( p )
	{
		q->front = q->front->next;
		p->next = NULL;

		free( p );

		p = q->front;
	}

	q->rear = NULL;
	q->num = 0;

}

                        5)销毁队列 

void DestroyQueue( LinkQueue * q )
{
    //队列不存在 
    if( q == NULL )
    {
		return ;
    }

    //遍历,删除每一个数据节点 (只允许在队首进行出队操作-->删除队首节点)
	ClearQueue( q );

    //释放队列的头结点
    free( q );
}

                        6)入队 
                            返回值:
                                1 入队成功
                                0 入队失败

int EnQueue( LinkQueue *q, ElemType d )
{
    //不能入队的情况: 队列不存在 
    if( q == NULL )
    {
		return 0;
    }

    //创建一个新的数据节点空间, 并初始化
    Node * pnew = (Node *)malloc( sizeof(Node) );
    pnew->data = d;
    pnew->next = NULL;

    //入队,只允许在队尾进行入队操作 --> 尾插法
    if( q->num == 0 )  //从无到有
    {
		q->front = pnew;
		q->rear = pnew;
    }
    else    //从少到多 
    {
		//尾插法
		q->rear->next = pnew;
		q->rear = pnew;
    }
    q->num ++;

    return 1;
}

                        7)出队 
                            返回值:
                                1 出队成功
                                0 出队失败

int DeQueue( LinkQueue *q, ElemType *d )
{
    //不能出队的情况: 队列不存在 || 队列为空 
    if( q == NULL || q->num == 0 )
    {
		return 0;
    }

    //出队,只允许在队首进行出队操作
    //先获取队首元素的值
	*d = q->front->data;
    
    //再出队(删除队首节点)
	Node * p = q->front;	//指向要删除的这个队首节点

	q->front = q->front->next;
	p->next = NULL;
	free( p );
	q->num --;

	if( q->num == 0 )	//仅剩的一个节点也被删除了,那么队尾rear也要被置NULL
	{
		q->rear = NULL;
	}

    return 1;
}

                        8)获取队首元素,但是不出队 (队首下标不变)
                            返回值: 
                                1 获取成功
                                0 获取失败 

int GetHead( LinkQueue *q, ElemType *d )
{
    //不能获取的情况: 队列不存在 || 队列为空 
    if( q == NULL || q->num == 0 )
    {
		return 0;
    }

    //获取队首元素的值,但是不出队
    *d = q->front->data;

    return 1;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值