數據結構-環形隊列 C和C++的實現


隊列:

含義:是一種先入先出(FIFO)的數據結構。

當我們把數據一個一個放入隊列中。當我們需要用到這些數據時,每次都從隊列的頭部取出第一個數據進行處理。就像排隊進場一樣,先排隊的人先進場。

結構如下圖所示

環形隊列:

含義:它是在寫程序時候一種隊列的特殊表達方式,把隊列數據組中的最后一個元素和第一個元素相連構成環,所以稱為環形隊列。

優點:環形隊列在C/C++編程中首元素出隊后不需要把隊列所有元素向前移動,而取代把把隊首指針向后移動,由於其環形結構,在插入元素后隊尾指針會循環到隊首原來的位置。相對普通隊列的出隊操作減少了大量的運算量。

 

C語言

程序清單:

本例中包含三個文件:

(插入圖片)

Queue.h:

#ifndef _QUEUE_H
#define _QUEUE_H
typedef unsigned char uint8_t;
typedef int Elem;

typedef struct circlequeue
{
    int iLength;
    int iSize;
    int iHead;
    int iTail;
    Elem *Datas; 
}Queue;

uint8_t  Queue_Init(Queue* queue,int size);
uint8_t Queue_Delete(Queue *queue);
uint8_t isQueueEmpty(Queue *queue);
uint8_t isQueueFull(Queue *queue);
int Queue_size(Queue *queue);
uint8_t Queue_push(Queue *queue,Elem data);
Elem Queue_front(Queue *queue);
Elem Queue_back(Queue *queue);
uint8_t Queue_pop(Queue *queue);
void Queue_printf(Queue *queue);

#endif
View Code

 

Queue.c:

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


/*******************************************************/
/*******************************************************/
/**********************創建隊列*************************/
/*******************************************************/
/*******************************************************/
uint8_t  Queue_Init(Queue* queue,int size)
{    
    queue->iSize = size;
    queue->iLength = 0;
    queue->iTail=0;
    queue->iHead=0;
    queue->Datas = (Elem *)malloc(size*sizeof(Elem));
    return 1;
}
/*******************************************************/
/*******************************************************/
/**********************刪除隊列*************************/
/*******************************************************/
/*******************************************************/
uint8_t Queue_Delete(Queue *queue)
{
    free(queue->Datas);
    return 1;
}
/*******************************************************/
/*******************************************************/
/*********************隊頭隊尾操作**********************/
/*******************************************************/
/*******************************************************/
static void QueueTailAdd(Queue *queue)
{
    queue->iTail++;
    queue->iTail = queue->iTail % queue->iSize;
}
static void QueueHeadAdd(Queue *queue)
{
    queue->iHead ++;
    queue->iHead = queue->iHead % queue->iSize;
}
/*******************************************************/
/*******************************************************/
/***********************隊列判空************************/
/*******************************************************/
/*******************************************************/
uint8_t isQueueEmpty(Queue *queue)
{
    if(queue->iLength == 0)
    {
        return 1;
    }
    return 0;    
}
/*******************************************************/
/*******************************************************/
/***********************隊列判滿************************/
/*******************************************************/
/*******************************************************/
uint8_t isQueueFull(Queue *queue)
{
    if(queue->iLength>=queue->iSize)
    {
        return 1;
    }
    return 0;
}
/*******************************************************/
/*******************************************************/
/*******************返回隊列現有長度********************/
/*******************************************************/
/*******************************************************/
int Queue_size(Queue *queue)
{
    return queue->iLength;
}
/*******************************************************/
/*******************************************************/
/********************往隊尾放入元素*********************/
/*******************************************************/
/*******************************************************/
uint8_t Queue_push(Queue *queue,Elem data)
{
    if(isQueueFull(queue))
    {
        return 0;
    }

    queue->Datas[queue->iTail] = data; 
    QueueTailAdd(queue);
    queue->iLength++;
    return 1;
}
/*******************************************************/
/*******************************************************/
/************獲取隊頭第一個元素(不刪除)***************/
/*******************************************************/
/*******************************************************/
Elem Queue_front(Queue *queue)
{
    if(isQueueEmpty(queue))
    {
        return 0;
    }

    return queue->Datas[queue->iHead];
}
Elem Queue_back(Queue *queue)
{
    if(isQueueEmpty (queue))
    {
        return 0;
    }
    return queue->Datas[queue->iTail];
}
/*******************************************************/
/*******************************************************/
/******************刪除隊列第一個元素*******************/
/*******************************************************/
/*******************************************************/
uint8_t Queue_pop(Queue *queue)
{
    if(isQueueEmpty(queue))
    {
        return 0;//queue empty
    }

    QueueHeadAdd(queue);
    queue->iLength--;
    return 1;
}
/*******************************************************/
/*******************************************************/
/*****************打印隊列中的全部元素******************/
/*******************************************************/
/*******************************************************/
void Queue_printf(Queue *queue)
{
    int i;
    int temp = queue->iHead;
    printf("queue datas:\r\n");
    for(i=0;i<queue->iLength;i++)
    {
        printf("%d ",queue->Datas[temp++%queue->iSize]);
    }
    printf("\r\n");
}
View Code

 

main.c(用於測試):

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


int main(void)
{
    int i;
    //queue(stack)
    Queue queue2[20];    
    //queue(heap)
    Queue *queue = (Queue*)malloc(sizeof(Queue)*20);
    //Queue Init
    Queue_Init(queue,20);
    Queue_Init(queue2,20);

    //queue1
    printf("insert datas:(0-19)\r\n");
    for(i=0;i<20;i++)
    {
        Queue_push(queue,i);
    }

    Queue_printf(queue);

    printf("delete datas(first 10):\r\n");
    for(i=0;i<10;i++)
    {
        Queue_pop(queue);
    }

    Queue_printf(queue);

    printf("first data:%d\r\n",Queue_front(queue));

    printf("queuesize = %d\r\n",Queue_size(queue));

    //queue2
    printf("\r\n");
    printf("insert datas to queue2:(0-190,10interval)\r\n");
    for(i=0;i<20;i++)
    {
        Queue_push(queue2,i*10);
    }

    Queue_printf(queue2);

    printf("delete datas(first 10):\r\n");
    for(i=0;i<10;i++)
    {
        Queue_pop(queue2);
    }

    Queue_printf(queue2);

    //delete queue
    printf("\r\n");
    printf("queue1 delete\r\n");
    Queue_Delete(queue);
    free(queue);
    queue=0;

    printf("queue2 delete\r\n");
    Queue_Delete(queue2);

    system("pause");
    return 0;
}
View Code

 

測試結果:

 

函數詳解:

環形隊列結構體:

在循環隊列中,有以下參數

必要參數:

  • 數據 *Datas;
  • 對尾索引 iTail;
  • 隊頭索引 iHead;

可選參數:

  • 隊列總大小 iSize;//隊列最大存放量,防止不當操作造成堆棧溢出
  • 隊列現在的長度 iLength;//儲存現在的長度減少運算量(不定義此參數可以通過隊頭隊尾索引差值計算長度)
typedef struct circlequeue
{
    int iLength;
    int iSize;
    int iHead;
    int iTail;
    Elem *Datas; 
}Queue;

 

創建隊列:

  1. 設置隊列的最大長度;
  2. 把隊列中的其他參數清零;
  3. 為隊列的數據區域申請內存;
uint8_t  Queue_Init(Queue* queue,int size)
{    
    queue->iSize = size;
    queue->iLength = 0;
    queue->iTail=0;
    queue->iHead=0;
    queue->Datas = (Elem *)malloc(size*sizeof(Elem));
    return 1;
}

 

 

入隊操作:

  1. 判斷隊列是否已滿,滿則無法插入,返回0插入失敗;
  2. 往隊尾插入數據
  3. 隊尾索引增加
  4. 隊列長度增加
uint8_t Queue_push(Queue *queue,Elem data)
{
    if(isQueueFull(queue))
    {
        return 0;
    }

    queue->Datas[queue->iTail] = data; 
    QueueTailAdd(queue);
    queue->iLength++;
    return 1;
}

 

出隊操作(分為兩部分)

出隊細分一、獲取隊頭元素但不刪除

  1. 判斷隊列是否為空,空則獲取失敗返回0;
  2. 返回隊列中隊頭索引指向元素
Elem Queue_front(Queue *queue)
{
    if(isQueueEmpty(queue))
    {
        return 0;
    }

    return queue->Datas[queue->iHead];
}

 

出隊細分二、刪除隊頭的元素但不返回其值

  1. 判斷隊列是否為空,空則刪除失敗;
  2. 增加隊頭索引;
  3. 減少隊列長度;
uint8_t Queue_pop(Queue *queue)
{
    if(isQueueEmpty(queue))
    {
        return 0;//queue empty
    }

    QueueHeadAdd(queue);
    queue->iLength--;
    return 1;
}

 

打印隊列中的元素、

創建一個temp等於隊頭索引,后邊打印中使用;

循環打印iLength(隊列長度)個數據;

從隊頭(temp)指向的元素開始打印,每打印一個數據后temp++(指向下一個元素),(特別說明:temp%queue->iSize取余數,當temp索引超過最大長度時自動返回數組頭開始打印,temp++%queue->iSize相當於兩步1、temp%queue->iSize 2、temp++)

void Queue_printf(Queue *queue)
{
    int i;
    int temp = queue->iHead;
    printf("queue datas:\r\n");
    for(i=0;i<queue->iLength;i++)
    {
        printf("%d ",queue->Datas[temp++%queue->iSize]);
    }
    printf("\r\n");
}

 

C++語言

 C++中思路和C基本類似,這里就不在贅述。上程序:

程序清單:

本部分包含三個文件:

(此處插入圖)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM