• 数据--第23课


    第23课 - 队列的优化实现

    1. 顺序队列的瓶颈

    顺序队列

    线性表的第一个元素作为队头。

    线性表的最后一个元素作为队尾。

    入队的新元素是线性表的最后,时间复杂度为O(1)。

    出队列时需要将后续的所有元素向前移动,时间复杂度是O(n)。

    2. 顺序队列的优化方案

    (1)定义front使其始终代表队头的下标。

    出队列时对头元素返回,且front++

    (2)定义rear使其始终代表队尾下一个元素的下标。

    出队时将新的元素插入,且rear++

    (3)没有必要只将下标为0的位置定义为队头。

    (4)顺序队列的关键状态

    初始状态:length == 0,front == 0,rear == 0;

    空队列状态:length == 0,front == rea;
             满队列状态:length == capacity,front == rea;

    (5)循环使用队列的空间

    入列:rear = (rear + 1) % capacity;

    出列:front = (front + 1) % capacity;

    3. 程序

    (1)LinkQueue2.0

    main.c

    #include <stdio.h>

    #include <stdlib.h>

    #include "LinkQueue.h"

    /* run this program using the console pauser or add your own getch, system("pause") or input loop */

    int main(int argc, char *argv[])

    {

        LinkQueue* queue = LinkQueue_Create();

        int a[10] = {0};

        int i = 0;

        for(i=0; i<10; i++)

        {

            a[i] = i + 1;     

            LinkQueue_Append(queue, a + i);

        }

        printf("Header: %d ", *(int*)LinkQueue_Header(queue));

        printf("Length: %d ", LinkQueue_Length(queue));  

        LinkQueue_Clear(queue);  

        while( LinkQueue_Length(queue) > 0 )

        {

            printf("Retrieve: %d ", *(int*)LinkQueue_Retrieve(queue));

        }  

        LinkQueue_Destroy(queue);

            return 0;

    }

    LinkQueue.h

    #ifndef _LINKQUEUE_H_

    #define _LINKQUEUE_H_

    typedef void LinkQueue;

    LinkQueue* LinkQueue_Create();

    void LinkQueue_Destroy(LinkQueue* queue);

    void LinkQueue_Clear(LinkQueue* queue);

    int LinkQueue_Append(LinkQueue* queue, void* item);

    void* LinkQueue_Retrieve(LinkQueue* queue);

    void* LinkQueue_Header(LinkQueue* queue);

    int LinkQueue_Length(LinkQueue* queue);

    #endif

    LinkQueue.c

    #include <malloc.h>

    #include <stdio.h>

    #include "LinkQueue.h"

    typedef struct _tag_LinkQueueNode TLinkQueueNode;

    struct _tag_LinkQueueNode

    {

        TLinkQueueNode* next;

        void* item;

    };

    typedef struct _tag_LinkQueue

    {

        TLinkQueueNode* front;

        TLinkQueueNode* rear;

        int length;

    } TLinkQueue;

    LinkQueue* LinkQueue_Create() // O(1)

    {

        TLinkQueue* ret = (TLinkQueue*)malloc(sizeof(TLinkQueue));

        if( ret != NULL )

        {

            ret->front = NULL;

            ret->rear = NULL;

            ret->length = 0;

        }

        return ret;

    }

    void LinkQueue_Destroy(LinkQueue* queue) // O(n)

    {

        LinkQueue_Clear(queue);

        free(queue);

    }

    void LinkQueue_Clear(LinkQueue* queue) // O(n)

    {

        while( LinkQueue_Length(queue) > 0 )

        {

            LinkQueue_Retrieve(queue);

        }

    }

    int LinkQueue_Append(LinkQueue* queue, void* item) // O(1)

    {

        TLinkQueue* sQueue = (TLinkQueue*)queue;

        TLinkQueueNode* node = (TLinkQueueNode*)malloc(sizeof(TLinkQueueNode));

        int ret = (sQueue != NULL ) && (item != NULL) && (node != NULL);

        if( ret )

        {

            node->item = item; 

            if( sQueue->length > 0 )

            {

                sQueue->rear->next = node;

                sQueue->rear = node;

                node->next = NULL;

            }

            else

            {

                sQueue->front = node;

                sQueue->rear = node;

                node->next = NULL;

            }

            sQueue->length++;

        }

        if( !ret )

        {

            free(node);

        }

        return ret;

    }

    void* LinkQueue_Retrieve(LinkQueue* queue) // O(1)

    {

        TLinkQueue* sQueue = (TLinkQueue*)queue;

        TLinkQueueNode* node = NULL;

        void* ret = NULL;

        if( (sQueue != NULL) && (sQueue->length > 0) )

        {

            node = sQueue->front;   

            sQueue->front = node->next;     

            ret = node->item;     

            free(node);      

            sQueue->length--;    

            if( sQueue->length == 0 )

            {

                sQueue->front = NULL;

                sQueue->rear = NULL;

            }

        } 

        return ret;

    }

    void* LinkQueue_Header(LinkQueue* queue) // O(1)

    {

        TLinkQueue* sQueue = (TLinkQueue*)queue;

        void* ret = NULL; 

        if( (sQueue != NULL) && (sQueue->length > 0) )

        {

            ret = sQueue->front->item;

        } 

        return ret;

    }

    int LinkQueue_Length(LinkQueue* queue) // O(1)

    {

        TLinkQueue* sQueue = (TLinkQueue*)queue;

        int ret = -1;   

        if( sQueue != NULL )

        {

            ret = sQueue->length;

        } 

        return ret;

    }

    (2)SeqQueue2.0

    main.c

    #include <stdio.h>

    #include <stdlib.h>

    #include "SeqQueue.h"

    /* run this program using the console pauser or add your own getch, system("pause") or input loop */

    int main(int argc, char *argv[])

    {

        SeqQueue* queue = SeqQueue_Create(6);

        int a[10] = {0};

        int i = 0;

        for(i=0; i<10; i++)

        {

            a[i] = i + 1;    

            SeqQueue_Append(queue, a + i);

        }  

        printf("Header: %d ", *(int*)SeqQueue_Header(queue));

        printf("Length: %d ", SeqQueue_Length(queue));

        printf("Capacity: %d ", SeqQueue_Capacity(queue));   

        while( SeqQueue_Length(queue) > 0 )

        {

            printf("Retrieve: %d ", *(int*)SeqQueue_Retrieve(queue));

        }  

        printf(" "); 

        for(i=0; i<10; i++)

        {

            a[i] = i + 1;       

            SeqQueue_Append(queue, a + i);

            printf("Retrieve: %d ", *(int*)SeqQueue_Retrieve(queue));

        }  

        SeqQueue_Destroy(queue);  

             return 0;

    }

    SeqQueue.h

    #ifndef _SEQQUEUE_H_

    #define _SEQQUEUE_H_

    typedef void SeqQueue;

    SeqQueue* SeqQueue_Create(int capacity);

    void SeqQueue_Destroy(SeqQueue* queue);

    void SeqQueue_Clear(SeqQueue* queue);

    int SeqQueue_Append(SeqQueue* queue, void* item);

    void* SeqQueue_Retrieve(SeqQueue* queue);

    void* SeqQueue_Header(SeqQueue* queue);

    int SeqQueue_Length(SeqQueue* queue);

    int SeqQueue_Capacity(SeqQueue* queue);

    #endif

    SeqQueue.c   

    #include <stdio.h>

    #include <malloc.h>

    #include "SeqQueue.h"

    typedef unsigned int TSeqQueueNode;

    typedef struct _tag_SeqQueue

    {

        int capacity;

        int length;

        int front;

        int rear;

        TSeqQueueNode* node;

    } TSeqQueue;

    SeqQueue* SeqQueue_Create(int capacity) // O(1)

    {

        TSeqQueue* ret = NULL;

        if( capacity >= 0 )

        {

            ret = (TSeqQueue*)malloc(sizeof(TSeqQueue) + sizeof(TSeqQueueNode) * capacity);

        }

        if( ret != NULL )

        {

            ret->capacity = capacity;

            ret->length = 0;

            ret->front = 0;

            ret->rear = 0;

            ret->node = (TSeqQueueNode*)(ret + 1);

        } 

        return ret;

    }

    void SeqQueue_Destroy(SeqQueue* queue) // O(1)

    {

        free(queue);

    }

    void SeqQueue_Clear(SeqQueue* queue) // O(1)

    {

        TSeqQueue* sQueue = (TSeqQueue*)queue;  

        if( sQueue != NULL )

        {

            sQueue->length = 0;

            sQueue->front = 0;

            sQueue->rear = 0;

        }

    }

    int SeqQueue_Append(SeqQueue* queue, void* item) // O(1)

    {

        TSeqQueue* sQueue = (TSeqQueue*)queue;

        int ret = (sQueue != NULL) && (item != NULL);

        ret = ret && (sQueue->length + 1 <= sQueue->capacity);

        if( ret )

        {

            sQueue->node[sQueue->rear] = (TSeqQueueNode)item;     

            sQueue->rear = (sQueue->rear + 1) % sQueue->capacity; 

            sQueue->length++;

        } 

        return ret;

    }

    void* SeqQueue_Retrieve(SeqQueue* queue) // O(1)

    {

        TSeqQueue* sQueue = (TSeqQueue*)queue;

        void* ret = SeqQueue_Header(queue);  

        if( ret != NULL )

        {

            sQueue->front = (sQueue->front + 1) % sQueue->capacity;     

            sQueue->length--;

        } 

        return ret;

    }

    void* SeqQueue_Header(SeqQueue* queue) // O(1)

    {

        TSeqQueue* sQueue = (TSeqQueue*)queue;

        void* ret = NULL;

        if( (sQueue != NULL) && (sQueue->length > 0) )

        {

            ret = (void*)(sQueue->node[sQueue->front]);

        }

        return ret;

    }

    int SeqQueue_Length(SeqQueue* queue) // O(1)

    {

        TSeqQueue* sQueue = (TSeqQueue*)queue;

        int ret = -1;

        if( sQueue != NULL )

        {

            ret = sQueue->length;

        }

        return ret;

    }

    int SeqQueue_Capacity(SeqQueue* queue) // O(1)

    {

        TSeqQueue* sQueue = (TSeqQueue*)queue;

             int ret = -1; 

        if( sQueue != NULL )

        {

            ret = sQueue->capacity;

        }  

        return ret;

    }

    4. 链式队列的瓶颈

    链式队列

    线性表的第一个元素作为队头。

    线性表的最后一个元素作为队尾。

    入队的新元素实在线性表的最后,时间复杂度是O(n)。

    出队的元素即链表的第一个元素,时间复杂度是O(1)。

    5. 优化方案

    (1)定义rear指针始终指向链表的最后一个元素,入队时将新的元素通过rear插入队尾,而且将rear指向新的元素。

    (2)链式队列的关键状态

    空队列状态:front == NULL, rear == NULL;

    关键操作:

    入队:

    rear ->next = node;

    rear = node;

    node ->next =NULL;

    出列:

    front = front ->next;

    6. 代码

    小结:

    (1)      优化的顺序队列循环利用顺序空间提高队列操作的效率。

    (2)      优化的链式队列定义rear指针指向队尾元素提高出队操作的效率。

    (3)      效率提高了,可实现的复杂性也提高了。

  • 相关阅读:
    [转]如何成为强大的程序员?
    Three.JS 学习准备(0)
    jsp生命周期
    form表单文件上传 servlet文件接收
    android 在自定义的listview(有刷新加载项)列表中,数据过少时不能铺满整个屏幕时,header和footer同时显示问题
    jsp处理
    保持listview当前位置
    HTML5应用:setCustomValidity(message)接口
    Hibernate 查询方法
    这个故事很好,希望激励自己前进······
  • 原文地址:https://www.cnblogs.com/free-1122/p/11335988.html
Copyright © 2020-2023  润新知