diff --git a/codes/c/chapter_stack_and_queue/CMakeLists.txt b/codes/c/chapter_stack_and_queue/CMakeLists.txt index 58c58aa8a..832f68380 100644 --- a/codes/c/chapter_stack_and_queue/CMakeLists.txt +++ b/codes/c/chapter_stack_and_queue/CMakeLists.txt @@ -2,3 +2,4 @@ add_executable(array_stack array_stack.c) add_executable(linkedlist_stack linkedlist_stack.c) add_executable(array_queue array_queue.c) add_executable(linkedlist_queue linkedlist_queue.c) +add_executable(array_deque array_deque.c) diff --git a/codes/c/chapter_stack_and_queue/array_deque.c b/codes/c/chapter_stack_and_queue/array_deque.c new file mode 100644 index 000000000..704a0a3ef --- /dev/null +++ b/codes/c/chapter_stack_and_queue/array_deque.c @@ -0,0 +1,171 @@ +/** + * File: array_deque.c + * Created Time: 2023-03-13 + * Author: Gonglja (glj0@outlook.com) + */ + +#include "../include/include.h" + +/* 基于环形数组形成的双向队列 */ +struct ArrayDeque { + int *nums; // 用于存储队列元素的数组 + int front; // 队首指针,指向队首元素 + int queSize; // 尾指针,指向队尾 + 1 + int queCapacity; // 队列容量 +}; + +typedef struct ArrayDeque ArrayDeque; + +/* 构造方法 */ +ArrayDeque *newArrayDeque(int capacity) { + ArrayDeque *deque = (ArrayDeque *) malloc(sizeof(ArrayDeque)); + // 初始化数组 + deque->queCapacity = capacity; + deque->nums = (int *) malloc(sizeof(int) * deque->queCapacity); + deque->front = deque->queSize = 0; + return deque; +} + +/* 析构方法 */ +void delArrayDeque(ArrayDeque *deque) { + free(deque->nums); + deque->queCapacity = 0; +} + +/* 获取双向队列的容量 */ +int capacity(ArrayDeque *deque) { + return deque->queCapacity; +} + +/* 获取双向队列的长度 */ +int size(ArrayDeque *deque) { + return deque->queSize; +} + +/* 判断双向队列是否为空 */ +bool empty(ArrayDeque *deque) { + return deque->queSize == 0; +} + +int dequeIndex(ArrayDeque *deque, int i) { + // 通过取余操作实现数组首尾相连 + // 当 i 越过数组尾部时,回到头部 + // 当 i 越过数组头部后,回到尾部 + return ((i + capacity(deque)) % capacity(deque)); +} + +/* 队首入队 */ +void pushFirst(ArrayDeque *deque, int num) { + if (deque->queSize == capacity(deque)) { + printf("双向队列已满\r\n"); + return; + } + // 队首指针向左移动一位 + // 通过取余操作,实现 front 越过数组头部回到尾部 + deque->front = dequeIndex(deque, deque->front - 1); + // 将 num 添加到队首 + deque->nums[deque->front] = num; + deque->queSize++; +} + +/* 队尾入队 */ +void pushLast(ArrayDeque *deque, int num) { + if (deque->queSize == capacity(deque)) { + printf("双向队列已满\r\n"); + return; + } + // 计算尾指针,指向队尾索引 + 1 + int rear = dequeIndex(deque, deque->front + deque->queSize); + // 将 num 添加至队尾 + deque->nums[rear] = num; + deque->queSize++; +} + +/* 访问队首元素 */ +int peekFirst(ArrayDeque *deque) { + // 访问异常:双向队列为空 + assert(empty(deque) == 0); + return deque->nums[deque->front]; +} + +/* 访问队尾元素 */ +int peekLast(ArrayDeque *deque) { + // 访问异常:双向队列为空 + assert(empty(deque) == 0); + int last = dequeIndex(deque, deque->front + deque->queSize - 1); + return deque->nums[last]; +} + +/* 队首出队 */ +int pollFirst(ArrayDeque *deque) { + int num = peekFirst(deque); + // 队首指针向后移动一位 + deque->front = dequeIndex(deque, deque->front + 1); + deque->queSize--; + return num; +} + +/* 队尾出队 */ +int pollLast(ArrayDeque *deque) { + int num = peekLast(deque); + deque->queSize--; + return num; +} + +/* 打印基于环形数组形成的队列 */ +void printArrayDeque(ArrayDeque *deque) { + int arr[deque->queSize]; + // 拷贝 + for (int i = 0, j = deque->front; i < deque->queSize; i++, j++) { + arr[i] = deque->nums[j % deque->queCapacity]; + } + printArray(arr, deque->queSize); +} + + +/* Driver Code */ +int main() { + /* 初始化队列 */ + int capacity = 10; + ArrayDeque *deque = newArrayDeque(capacity); + pushLast(deque, 3); + pushLast(deque, 2); + pushLast(deque, 5); + printf("双向队列 deque = "); + printArrayDeque(deque); + + /* 访问元素 */ + int peekFirstNum = peekFirst(deque); + printf("队首元素 peekFirst = %d\r\n", peekFirstNum); + int peekLastNum = peekLast(deque); + printf("队尾元素 peekLast = %d\r\n", peekLastNum); + + /* 元素入队 */ + pushLast(deque, 4); + printf("元素 4 队尾入队后 deque = "); + printArrayDeque(deque); + pushFirst(deque, 1); + printf("元素 1 队首入队后 deque = "); + printArrayDeque(deque); + + /* 元素出队 */ + int pollLastNum = pollLast(deque); + printf("队尾出队元素 = %d,队尾出队后 deque= ", pollLastNum); + printArrayDeque(deque); + int pollFirstNum = pollFirst(deque); + printf("队首出队元素 = %d,队首出队后 deque= ", pollFirstNum); + printArrayDeque(deque); + + /* 获取队列的长度 */ + int dequeSize = size(deque); + printf("双向队列长度 size = %d\r\n", dequeSize); + + /* 判断队列是否为空 */ + bool isEmpty = empty(deque); + printf("队列是否为空 = %s\r\n", isEmpty ? "true" : "false"); + + // 释放内存 + delArrayDeque(deque); + + return 0; +}