C实现队列

191 阅读2分钟

队列的定义

队列的实现

通用头文件 fatal.h

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

#define Error( Str )        FatalError( Str )
#define FatalError( Str )   fprintf( stderr, "%s\n", Str ), exit( 1 )

声明头文件 queue.h

typedef int ElementType;
#ifndef _Queue_h
#define _Queue_h

struct QueueRecord;
typedef struct QueueRecord *Queue;

int IsEmpty( Queue Q );
int IsFull( Queue Q );
Queue CreateQueue( int MaxElements );
void DisposeQueue( Queue Q );
void MakeEmpty( Queue Q );
void Enqueue( ElementType X, Queue Q );
ElementType Front( Queue Q );
void Dequeue( Queue Q );
ElementType FrontAndDequeue( Queue Q );

#endif  /* _Queue_h */

队列实现 queue.c

        #include "queue.h"
        #include "fatal.h"
        #include <stdlib.h>

        #define MinQueueSize ( 5 )

        struct QueueRecord
        {
            int Capacity; // 队列容量
            int Front; // 指向队列头部位置
            int Rear; // 指向队列尾部位置
            int Size; // 目前队列中元素的数量
            ElementType *Array; // 存放元素的数组
        };

        int
        IsEmpty( Queue Q )
        {
        	// 只通过size来判断是否空队列
            return Q->Size == 0;
        }

        int
        IsFull( Queue Q )
        {
            return Q->Size == Q->Capacity;
        }

        Queue
        CreateQueue( int MaxElements )
        {
            Queue Q;

/* 1*/      if( MaxElements < MinQueueSize )
/* 2*/          Error( "Queue size is too small" );

/* 3*/      Q = malloc( sizeof( struct QueueRecord ) );
/* 4*/      if( Q == NULL )
/* 5*/          FatalError( "Out of space!!!" );

/* 6*/      Q->Array = malloc( sizeof( ElementType ) * MaxElements );
/* 7*/      if( Q->Array == NULL )
/* 8*/          FatalError( "Out of space!!!" );
/* 9*/      Q->Capacity = MaxElements;
/*10*/      MakeEmpty( Q );

/*11*/      return Q;
        }

        void
        MakeEmpty( Queue Q )
        {
            Q->Size = 0;
            // Front 默认为1 因为空队列只能先入列 此时Rear由0 -> 1,所以为了Front可以访问到队列首元素 需要将它的默认值设为1
            Q->Front = 1;
            Q->Rear = 0;
        }

        void
        DisposeQueue( Queue Q )
        {
            if( Q != NULL )
            {
                free( Q->Array );
                free( Q );
            }
        }


        static int
        Succ( int Value, Queue Q )
        {
        	// 循环队列 Front或者Rear到达数组尾部的时候自动变为首位置0 也可以通过取余来实现
            if( ++Value == Q->Capacity )
                Value = 0;
            return Value;
        }

        void
        Enqueue( ElementType X, Queue Q )
        {
            if( IsFull( Q ) )
                Error( "Full queue" );
            else
            {
                Q->Size++;
                Q->Rear = Succ( Q->Rear, Q );
                Q->Array[ Q->Rear ] = X;
            }
        }



        ElementType
        Front( Queue Q )
        {
            if( !IsEmpty( Q ) )
                return Q->Array[ Q->Front ];
            Error( "Empty queue" );
            return 0;  /* Return value used to avoid warning */
        }

        void
        Dequeue( Queue Q )
        {
            if( IsEmpty( Q ) )
                Error( "Empty queue" );
            else
            {
                Q->Size--;
                Q->Front = Succ( Q->Front, Q );
            }
        }

        ElementType
        FrontAndDequeue( Queue Q )
        {
            ElementType X = 0;

            if( IsEmpty( Q ) )
                Error( "Empty queue" );
            else
            {
                Q->Size--;
                X = Q->Array[ Q->Front ];
                Q->Front = Succ( Q->Front, Q );
            }
            return X;
        }

测试代码 testque.c

#include <stdio.h>
#include "queue.h"

main( )
{
    Queue Q;
    int i;

    Q = CreateQueue( 12 );

    for( i = 0; i < 10; i++ )
        Enqueue( i, Q );

    while( !IsEmpty( Q ) )
    {
        printf( "%d\n", Front( Q ) );
        Dequeue( Q );
    }
    for( i = 0; i < 10; i++ )
        Enqueue( i, Q );

    while( !IsEmpty( Q ) )
    {
        printf( "%d\n", Front( Q ) );
        Dequeue( Q );
    }

    DisposeQueue( Q );
    return 0;
}

队列实战 leetcode 862题

返回 A 的最短的非空连续子数组的长度,该子数组的和至少为 K 。

如果没有和至少为 K 的非空子数组,返回 -1 。

 

示例 1:

输入:A = [1], K = 1

输出:1

示例 2:

输入:A = [1,2], K = 4

输出:-1

示例 3:

输入:A = [2,-1,2], K = 3

输出:3  

提示:

1 <= A.length <= 50000

-10 ^ 5 <= A[i] <= 10 ^ 5

1 <= K <= 10 ^ 9

解答

int shortestSubarray(int* A, int ASize, int K){
    int min = ASize + 1;

    // 存放索引的队列 这是一个单调升序队列
    int *queue = malloc(sizeof(int)*(ASize + 1));
    // 存放前缀和的数组
    int *sumList = malloc(sizeof(int)*(ASize + 1));

    sumList[0] = 0;
    for(int i=0;i<ASize;++i)
        // sumList[0] = 0, sumList[1] = sumList[0] + A[0], sumList[2] = sumList[1] + A[1], sumList[i+1] = sumList[i] + A[i]
        sumList[i+1] = sumList[i] + A[i];

    // 队首指针 队尾指针
    int front = 0, rear = 0;
    // 需要遍历sumList 所以是ASize + 1
    for(int i = 0;i< ASize + 1;++i) 
    {
        // 维持单调有序 如果新的i对应的sumList[i] 小于 队尾元素对应的sumList[queue[rear - 1]] 说明这是一个负数 
        // 那我们为了维持单调性就把不符合单调性的都从尾部弹出 
        while(front < rear && sumList[queue[rear - 1]] > sumList[i])
            --rear;

        // 新的索引入队列
        queue[rear++] = i;

        // 每次新的索引入队列了 我们需要计算一下 sumList[i] - sumList[queue[front]] 是否满足条件 
        // 是的话就移动队首指针并动态更新最小值 每次新的索引入列 会引起队列的更新
        while(front < rear && sumList[i] - sumList[queue[front]] >= K)
        {
            int count = i - queue[front];
            min = min < count ? min : count;
            ++front;
        }
    }
    return min == ASize + 1  ? -1 : min;
}