数据--第24课 - 队列的特别实现

第24课 - 队列的特别实现

 

讨论:

A: 重新实现的方式确实提高了顺序队列和链式队列的效率,可是实现过程还是比较复杂的。

B: 这也是没有办法的事,直接复用链表虽然可以实现队列,但是效率不好。

C: 有没有既能复用之前的代码,又能高效实现队列。

 

1. 思路

准备两个栈用于实现队列:inStack和outStack

当有新元素入队时:将其压入inStack

当需要出队时:
         当outStack为空时:

将inStack中的元素逐一弹出并压入outStack中。

将outStack的栈顶元素弹出。

当outStack不为空时:

直接将outStack的栈顶元素弹出。

 

2. 算法框架

Append(queue,node)

{

         Push(inStack,node);

}

Retrieve(queue)

{

         if(Size(outStack) == 0)

         {

                  while(Size(inStack)>0)

                  {

                           Push(outStack,Pop(inStack));  

                  }       

         }

         return Pop(outStack);

}

 

3. 程序

main.c

#include <stdio.h>

#include <stdlib.h>

#include "SQueue.h"

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

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

{

    SQueue* queue = SQueue_Create();

    int a[10] = {0};

    int i = 0;  

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

    {

        a[i] = i + 1;      

        SQueue_Append(queue, a + i);

    }  

    printf("Header: %d\n", *(int*)SQueue_Header(queue));

    printf("Length: %d\n", SQueue_Length(queue));  

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

    {

        printf("Retrieve: %d\n", *(int*)SQueue_Retrieve(queue));

    }  

    printf("Header: %d\n", *(int*)SQueue_Header(queue));

    printf("Length: %d\n", SQueue_Length(queue));  

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

    {

        a[i] = i + 1;      

        SQueue_Append(queue, a + i);

    }  

    while( SQueue_Length(queue) > 0 )

    {

        printf("Retrieve: %d\n", *(int*)SQueue_Retrieve(queue));

    }  

    SQueue_Destroy(queue); 

         return 0;

}

LinkList.c

LinkList.h

LinkStack.h

#ifndef _LINKSTACK_H_

#define _LINKSTACK_H_

typedef void LinkStack;

LinkStack* LinkStack_Create();

void LinkStack_Destroy(LinkStack* stack);

void LinkStack_Clear(LinkStack* stack);

int LinkStack_Push(LinkStack* stack, void* item);

void* LinkStack_Pop(LinkStack* stack);

void* LinkStack_Top(LinkStack* stack);

int LinkStack_Size(LinkStack* stack);

#endif

LinkStack.c

#include <malloc.h>

#include "LinkStack.h"

#include "LinkList.h"

typedef struct _tag_LinkStackNode

{

    LinkListNode header;

    void* item;

} TLinkStackNode;

LinkStack* LinkStack_Create()

{

    return LinkList_Create();

}

void LinkStack_Destroy(LinkStack* stack)

{

    LinkStack_Clear(stack);

    LinkList_Destroy(stack);

}

void LinkStack_Clear(LinkStack* stack)

{

    while( LinkStack_Size(stack) > 0 )

    {

        LinkStack_Pop(stack);

    }

}

int LinkStack_Push(LinkStack* stack, void* item)

{

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

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

    if( ret )

    {

        node->item = item; 

        ret  = LinkList_Insert(stack, (LinkListNode*)node, 0);

    }

    if( !ret )

    {

        free(node);

    }

    return ret;

}

void* LinkStack_Pop(LinkStack* stack)

{

    TLinkStackNode* node = (TLinkStackNode*)LinkList_Delete(stack, 0);

    void* ret = NULL;   

    if( node != NULL )

    {

        ret = node->item;     

        free(node);

    } 

    return ret;

}

void* LinkStack_Top(LinkStack* stack)

{

    TLinkStackNode* node = (TLinkStackNode*)LinkList_Get(stack, 0);

    void* ret = NULL;  

    if( node != NULL )

    {

        ret = node->item;

    } 

    return ret;

}

int LinkStack_Size(LinkStack* stack)

{

    return LinkList_Length(stack);

}

 

 

SQueue.h

#ifndef _SQUEUE_H_

#define _SQUEUE_H_

typedef void SQueue;

SQueue* SQueue_Create();

void SQueue_Destroy(SQueue* queue);

void SQueue_Clear(SQueue* queue);

int SQueue_Append(SQueue* queue, void* item);

void* SQueue_Retrieve(SQueue* queue);

void* SQueue_Header(SQueue* queue);

int SQueue_Length(SQueue* queue);

#endif

SQueue.c

#include <stdio.h>

#include <malloc.h>

#include "LinkStack.h"

#include "SQueue.h"

typedef struct _tag_SQueue

{

    LinkStack* inStack;

    LinkStack* outStack;

} TSQueue;

SQueue* SQueue_Create() // O(1)

{

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

    if( ret != NULL )

    {

        ret->inStack = LinkStack_Create();

        ret->outStack = LinkStack_Create();  

        if( (ret->inStack == NULL) || (ret->outStack == NULL) )

        {

            LinkStack_Destroy(ret->inStack);

            LinkStack_Destroy(ret->outStack);          

            free(ret);          

            ret = NULL;

        }

    }  

    return ret;

}

void SQueue_Destroy(SQueue* queue) // O(n)

{

    SQueue_Clear(queue);

    free(queue);

}

void SQueue_Clear(SQueue* queue) // O(n)

{

    TSQueue* sQueue = (TSQueue*)queue;

    if( sQueue != NULL )

    {

        LinkStack_Clear(sQueue->inStack);

        LinkStack_Clear(sQueue->outStack);

    }

}

int SQueue_Append(SQueue* queue, void* item) // O(1)

{

    TSQueue* sQueue = (TSQueue*)queue; 

    if( sQueue != NULL )

    {

        LinkStack_Push(sQueue->inStack, item);

    }

}

void* SQueue_Retrieve(SQueue* queue) // O(1)

{

    TSQueue* sQueue = (TSQueue*)queue;

    void* ret = NULL; 

    if( sQueue != NULL )

    {

        if( LinkStack_Size(sQueue->outStack) == 0 )

        {

            while( LinkStack_Size(sQueue->inStack) > 0 )

            {

                LinkStack_Push(sQueue->outStack, LinkStack_Pop(sQueue->inStack));

            }

        }     

        ret = LinkStack_Pop(sQueue->outStack);

    } 

    return ret;

}

void* SQueue_Header(SQueue* queue) // O(1)

{

    TSQueue* sQueue = (TSQueue*)queue;

    void* ret = NULL;  

    if( sQueue != NULL )

    {

        if( LinkStack_Size(sQueue->outStack) == 0 )

        {

            while( LinkStack_Size(sQueue->inStack) > 0 )

            {

                LinkStack_Push(sQueue->outStack, LinkStack_Pop(sQueue->inStack));

            }

        }   

        ret = LinkStack_Top(sQueue->outStack);

    }   

    return ret;

}

int SQueue_Length(SQueue* queue) // O(1)

{

    TSQueue* sQueue = (TSQueue*)queue;

    int ret = -1;   

    if( sQueue != NULL )

    {

        ret = LinkStack_Size(sQueue->inStack) + LinkStack_Size(sQueue->outStack);

    }   

    return ret;

}

 

小结:

组合使用两个栈的“后进先出”可以实现队列的“先进先出”

两个栈实现队列的方法复用栈数据结构,实现过程简单而且高效。

两个栈实现的队列操作的时间复杂度能够达到O(1)。

 

posted @ 2019-08-11 18:32  free-锻炼身体  阅读(121)  评论(0编辑  收藏  举报