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