2 changed files with 140 additions and 0 deletions
@ -0,0 +1,99 @@ |
|||||||
|
/* sliding_window_min.c */ |
||||||
|
#include "sliding_window_min.h" |
||||||
|
#include <stdlib.h> |
||||||
|
#include <limits.h> |
||||||
|
|
||||||
|
struct SlidingWindowMin { |
||||||
|
int* data; /* кольцевой буфер значений */ |
||||||
|
int* deq; /* deque индексов (тоже кольцевой) */ |
||||||
|
int dq_head; |
||||||
|
int dq_tail; |
||||||
|
int deq_count; |
||||||
|
int cur_pos; |
||||||
|
int window_size; |
||||||
|
}; |
||||||
|
|
||||||
|
SlidingWindowMin* swm_create(int window_size) |
||||||
|
{ |
||||||
|
if (window_size <= 0) { |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
SlidingWindowMin* swm = (SlidingWindowMin*)malloc(sizeof(SlidingWindowMin)); |
||||||
|
if (!swm) { |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
swm->data = (int*)malloc((size_t)window_size * sizeof(int)); |
||||||
|
if (!swm->data) { |
||||||
|
free(swm); |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
swm->deq = (int*)malloc((size_t)window_size * sizeof(int)); |
||||||
|
if (!swm->deq) { |
||||||
|
free(swm->data); |
||||||
|
free(swm); |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
swm->window_size = window_size; |
||||||
|
swm->dq_head = 0; |
||||||
|
swm->dq_tail = 0; |
||||||
|
swm->deq_count = 0; |
||||||
|
swm->cur_pos = 0; |
||||||
|
|
||||||
|
return swm; |
||||||
|
} |
||||||
|
|
||||||
|
void swm_destroy(SlidingWindowMin* swm) |
||||||
|
{ |
||||||
|
if (swm) { |
||||||
|
free(swm->data); |
||||||
|
free(swm->deq); |
||||||
|
free(swm); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void swm_add(SlidingWindowMin* swm, int val) |
||||||
|
{ |
||||||
|
if (!swm) return; |
||||||
|
|
||||||
|
int idx = swm->cur_pos; |
||||||
|
int w = swm->window_size; |
||||||
|
|
||||||
|
/* записываем в кольцевой буфер */ |
||||||
|
swm->data[idx % w] = val; |
||||||
|
|
||||||
|
/* 1. удаляем из начала deque индексы, которые уже вышли за окно */ |
||||||
|
while (swm->deq_count > 0 && swm->deq[swm->dq_head] <= idx - w) { |
||||||
|
swm->dq_head = (swm->dq_head + 1) % w; |
||||||
|
swm->deq_count--; |
||||||
|
} |
||||||
|
|
||||||
|
/* 2. удаляем из хвоста все элементы, которые хуже текущего */ |
||||||
|
while (swm->deq_count > 0) { |
||||||
|
int last_idx = swm->deq[(swm->dq_tail - 1 + w) % w]; |
||||||
|
if (swm->data[last_idx % w] < val) { |
||||||
|
break; |
||||||
|
} |
||||||
|
swm->dq_tail = (swm->dq_tail - 1 + w) % w; |
||||||
|
swm->deq_count--; |
||||||
|
} |
||||||
|
|
||||||
|
/* 3. добавляем текущий индекс */ |
||||||
|
swm->deq[swm->dq_tail] = idx; |
||||||
|
swm->dq_tail = (swm->dq_tail + 1) % w; |
||||||
|
swm->deq_count++; |
||||||
|
|
||||||
|
swm->cur_pos++; |
||||||
|
} |
||||||
|
|
||||||
|
int swm_get_min(const SlidingWindowMin* swm) |
||||||
|
{ |
||||||
|
if (!swm || swm->deq_count == 0) { |
||||||
|
return INT_MAX; |
||||||
|
} |
||||||
|
int min_idx = swm->deq[swm->dq_head]; |
||||||
|
return swm->data[min_idx % swm->window_size]; |
||||||
|
} |
||||||
@ -0,0 +1,41 @@ |
|||||||
|
/* sliding_window_min.h */ |
||||||
|
#ifndef SLIDING_WINDOW_MIN_H |
||||||
|
#define SLIDING_WINDOW_MIN_H |
||||||
|
|
||||||
|
#include <stddef.h> /* для size_t */ |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
extern "C" { |
||||||
|
#endif |
||||||
|
|
||||||
|
typedef struct SlidingWindowMin SlidingWindowMin; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Создаёт новую структуру скользящего минимума. |
||||||
|
* @param window_size размер окна (должен быть > 0) |
||||||
|
* @return указатель на структуру или NULL при ошибке выделения памяти |
||||||
|
*/ |
||||||
|
SlidingWindowMin* swm_create(int window_size); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Уничтожает структуру и освобождает всю динамически выделенную память. |
||||||
|
*/ |
||||||
|
void swm_destroy(SlidingWindowMin* swm); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Добавляет новое значение в окно. |
||||||
|
* После вызова swm_get_min() сразу вернёт минимум последних min(window_size, добавленных) значений. |
||||||
|
*/ |
||||||
|
void swm_add(SlidingWindowMin* swm, int val); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает текущий минимум в окне. |
||||||
|
* Если окно пустое — возвращает INT_MAX. |
||||||
|
*/ |
||||||
|
int swm_get_min(const SlidingWindowMin* swm); |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif /* SLIDING_WINDOW_MIN_H */ |
||||||
Loading…
Reference in new issue