队列的定义
队列的实现
通用头文件 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;
}