第18課——隊列的優化實現
阿新 • • 發佈:2018-09-02
eat kqueue nts 鏈式隊列 進棧 實現 lin clu 代碼
之前實現的順序棧和鏈式棧的進棧和出棧操作時間復雜度都是O(1)。而用同樣的方式實現隊列,進隊和出隊的復雜度總有一個是O(n) 。
順序隊列的瓶頸
順序隊列
線性表的第一個元素作為隊頭
線性表的最後一個元素作為隊尾
入隊的新元素是在線性表的最後,時間復雜度為O(1);
出隊時需要將後續的所有元素向前移動,時間復雜度為O(n);
順序隊列的優化方案
定義順序隊列的頭:
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; }
入隊列
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; }
出隊列由原來的O(n)變成的O(1);
完整版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; }SeqQueue.c
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\n", *(int*)SeqQueue_Header(queue)); printf("Length: %d\n", SeqQueue_Length(queue)); printf("Capacity: %d\n", SeqQueue_Capacity(queue)); while( SeqQueue_Length(queue) > 0 ) { printf("Retrieve: %d\n", *(int*)SeqQueue_Retrieve(queue)); } printf("\n"); for(i=0; i<10; i++) { a[i] = i + 1; SeqQueue_Append(queue, a + i); printf("Retrieve: %d\n", *(int*)SeqQueue_Retrieve(queue)); } SeqQueue_Destroy(queue); return 0; }
運行結果為:
同樣的,我們來實現鏈式隊列;
鏈式隊列的頭:
typedef struct _tag_LinkQueue { TLinkQueueNode* front; TLinkQueueNode* rear; int length; } TLinkQueue;
節點:
struct _tag_LinkQueueNode { TLinkQueueNode* next; void* item; };
創建:
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; }
入隊列:
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; }
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\n", *(int*)LinkQueue_Header(queue)); printf("Length: %d\n", LinkQueue_Length(queue)); // LinkQueue_Clear(queue); while( LinkQueue_Length(queue) > 0 ) { printf("Retrieve: %d\n", *(int*)LinkQueue_Retrieve(queue)); } LinkQueue_Destroy(queue); return 0; }
運行結果:
優化後的隊列,增加了front,rear後,入隊和出隊都是O(1);
第18課——隊列的優化實現