UP 路径优化

This commit is contained in:
JiXieShi
2024-09-13 22:38:08 +08:00
parent d7d34508d6
commit 590ac774dd
34 changed files with 13 additions and 183 deletions

43
lib/list/array.cpp Normal file
View File

@@ -0,0 +1,43 @@
#include <cstdlib>
#include "array.h"
void insert(int *nums, int size, int num, int index) {
// 把索引 index 以及之后的所有元素向后移动一位
for (int i = size - 1; i > index; i--) {
nums[i] = nums[i - 1];
}
// 将 num 赋给 index 处的元素
nums[index] = num;
}
void removeItem(int *nums, int size, int index) {
// 把索引 index 之后的所有元素向前移动一位
for (int i = index; i < size - 1; i++) {
nums[i] = nums[i + 1];
}
}
int find(int *nums, int size, int target) {
for (int i = 0; i < size; i++) {
if (nums[i] == target)
return i;
}
return -1;
}
/* 扩展数组长度 */
int *extend(int *nums, int size, int enlarge) {
// 初始化一个扩展长度后的数组
int *res = (int *) malloc(sizeof(int) * (size + enlarge));
// 将原数组中的所有元素复制到新数组
for (int i = 0; i < size; i++) {
res[i] = nums[i];
}
// 初始化扩展后的空间
for (int i = size; i < size + enlarge; i++) {
res[i] = 0;
}
// 返回扩展后的新数组
return res;
}

32
lib/list/inc/array.h Normal file
View File

@@ -0,0 +1,32 @@
#ifndef HW_LIB_ARRAY_H
#define HW_LIB_ARRAY_H
#ifdef __cplusplus
extern "C" {
#endif
// 在数组的索引 index 处插入元素 num
// nums: 操作数组
// size: 数组大小
// num: 操作数
// index: 操作位置
void insert(int *nums, int size, int num, int index);
// 删除索引 index 处的元素
// nums: 操作数组
// size: 数组大小
// index: 索引位置
// 注意stdio.h 占用了 remove 关键词
void removeItem(int *nums, int size, int index);
// 在数组中查找指定元素
// nums: 操作数组
// size: 数组大小
// target: 查找元素
int find(int *nums, int size, int target);
/* 扩展数组长度 */
int *extend(int *nums, int size, int enlarge);
#ifdef __cplusplus
}
#endif
#endif //HW_LIB_ARRAY_H

149
lib/list/inc/list.h Normal file
View File

@@ -0,0 +1,149 @@
#pragma once
#ifndef HW_LIB_LIST_H
#define HW_LIB_LIST_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
typedef struct List_Node_t { //节点结构
void *data;
struct List_Node_t *next;
} List_Node_t;
typedef struct{ //链表结构
List_Node_t *head;
List_Node_t *tail;
long len;
} List_t;
/**
* @brief 初始化链表
* @param list: [输入] 链表指针
* @return void
* @example list_init(&myList_t);
*/
extern void list_init(List_t *list);
/**
* @brief 检查链表是否为空
* @param list: [输入] 链表指针
* @return bool 若链表为空返回true否则返回false
* @example if (list_is_empty(&myList_t)) { // do something }
*/
extern bool list_is_empty(List_t *list);
/**
* @brief 在链表尾部插入元素
* @param list: [输入] 链表指针
* @param data: [输入] 待插入的数据指针
* @return void
* @example list_insert(&myList_t, newData);
*/
extern void list_insert(List_t *list, void *data);
/**
* @brief 在链表头部插入元素
* @param list: [输入] 链表指针
* @param data: [输入] 待插入的数据指针
* @return void
* @example list_insert_at_head(&myList_t, newData);
*/
extern void list_insert_at_head(List_t *list, void *data);
/**
* @brief 在链表尾部插入元素
* @param list: [输入] 链表指针
* @param data: [输入] 待插入的数据指针
* @return void
* @example list_insert_at_tail(&myList_t, newData);
*/
extern void list_insert_at_tail(List_t *list, void *data);
/**
* @brief 在指定位置插入元素
* @param list: [输入] 链表指针
* @param data: [输入] 待插入的数据指针
* @param idx: [输入] 插入位置索引
* @return void
* @example list_insert_at_index(&myList_t, newData, 2);
*/
extern void list_insert_at_index(List_t *list, void *data, long idx);
/**
* @brief 删除链表中指定元素
* @param list: [输入] 链表指针
* @param key: [输入] 待删除的数据指针
* @param compare: [输入] 比较函数指针
* @return void* 返回被删除元素的数据若未找到返回NULL
* @example deletedData = list_delete(&myList_t, keyData, compareFunc);
*/
extern void *list_delete(List_t *list, void *key, int (*compare)(const void *, const void *));
/**
* @brief 在链表中查找指定元素
* @param list: [输入] 链表指针
* @param key: [输入] 待查找的数据指针
* @param compare: [输入] 比较函数指针
* @return void* 返回找到的元素的数据若未找到返回NULL
* @example foundData = list_search(&myList_t, keyData, compareFunc);
*/
extern void *list_search(List_t *list, void *key, int (*compare)(const void *, const void *));
/**
* @brief 对链表进行排序
* @param list: [输入] 链表指针
* @param compare: [输入] 比较函数指针
* @return void
* @example list_sort(&myList_t, compareFunc);
*/
extern void list_sort(List_t *list, int (*compare)(const void *, const void *));
/**
* @brief 遍历链表并对每个元素执行指定操作
* @param list: [输入] 链表指针
* @param handle: [输入] 处理函数指针
* @return void
* @example list_traverse(&myList_t, handleFunc);
*/
extern void list_traverse(List_t *list, void (*handle)(void *));
/**
* @brief 反转链表
* @param list: [输入] 链表指针
* @return void
* @example list_reverse(&myList_t);
*/
extern void list_reverse(List_t *list);
/**
* @brief 获取链表长度
* @param list: [输入] 链表指针
* @return long 返回链表中元素个数
* @example length = list_get_lenth(&myList_t);
*/
extern long list_get_lenth(List_t *list);
/**
* @brief 获取链表指定位置的元素
* @param list: [输入] 链表指针
* @param idx: [输入] 元素索引
* @return void* 返回指定位置的元素指针若索引无效返回NULL
* @example element = list_get_element(&myList_t, 3);
*/
extern void *list_get_element(List_t *list, int idx);
/**
* @brief 销毁链表
* @param list: [输入] 链表指针
* @param destroy: [输入] 数据销毁函数指针
* @return void
* @example list_destroy(&myList_t, destroyFunc);
*/
extern void list_destroy(List_t *list, void (*destroy)(void *data));
#ifdef __cplusplus
}
#endif
#endif //HW_LIB_LIST_H

111
lib/list/inc/queue.h Normal file
View File

@@ -0,0 +1,111 @@
#pragma once
#ifndef HW_LIB_QUEUE_H
#define HW_LIB_QUEUE_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief 双向链表节点结构体
*/
typedef struct Queue_Node_t {
void *val; // 节点值
struct Queue_Node_t *next; // 后继节点
struct Queue_Node_t *prev; // 前驱节点
} Queue_Node_t;
/**
* @brief 双端队列结构体
*/
typedef struct {
Queue_Node_t *front, *rear; // 头节点 front ,尾节点 rear
int queSize; // 双向队列的长度
size_t typeSize; // 元素类型的大小
} Queue_List_t;
/**
* @brief 创建一个新的双端队列
* @param typeSize: [输入] 元素类型的大小
* @return Queue_List_t* 返回新创建的双端队列指针
* @example deque = newQueue_List(sizeof(int));
*/
extern Queue_List_t *newQueue_List(unsigned char size);
/**
* @brief 销毁双端队列
* @param deque: [输入] 双端队列指针
* @return void
* @example delQueue_List(deque);
*/
extern void delQueue_List(Queue_List_t *deque);
/**
* @brief 获取队列大小
* @param deque: [输入] 双端队列指针
* @return int 返回队列中元素个数
* @example size = queue_size(deque);
*/
extern int queue_size(Queue_List_t *deque);
/**
* @brief 检查队列是否为空
* @param deque: [输入] 双端队列指针
* @return bool 若队列为空返回true否则返回false
* @example if (queue_is_empty(deque)) { // do something }
*/
extern bool queue_is_empty(Queue_List_t *deque);
/**
* @brief 在队列头部插入元素
* @param deque: [输入] 双端队列指针
* @param data: [输入] 待插入的数据指针
* @return void
* @example pushFirst(deque, newData);
*/
extern void pushFirst(Queue_List_t *deque, void *data);
/**
* @brief 在队列尾部插入元素
* @param deque: [输入] 双端队列指针
* @param data: [输入] 待插入的数据指针
* @return void
* @example pushLast(deque, newData);
*/
extern void pushLast(Queue_List_t *deque, void *data);
/**
* @brief 获取队列头部元素但不移除
* @param deque: [输入] 双端队列指针
* @return void* 返回队列头部元素的指针若队列为空返回NULL
* @example firstData = peekFirst(deque);
*/
extern void *peekFirst(Queue_List_t *deque);
/**
* @brief 获取队列尾部元素但不移除
* @param deque: [输入] 双端队列指针
* @return void* 返回队列尾部元素的指针若队列为空返回NULL
* @example lastData = peekLast(deque);
*/
extern void *peekLast(Queue_List_t *deque);
/**
* @brief 弹出队列头部元素
* @param deque: [输入] 双端队列指针
* @return void* 返回被弹出的头部元素的指针若队列为空返回NULL
* @example poppedData = popFirst(deque);
*/
extern void *popFirst(Queue_List_t *deque);
/**
* @brief 弹出队列尾部元素
* @param deque: [输入] 双端队列指针
* @return void* 返回被弹出的尾部元素的指针若队列为空返回NULL
* @example poppedData = popLast(deque);
*/
extern void *popLast(Queue_List_t *deque);
#ifdef __cplusplus
}
#endif
#endif //HW_LIB_QUEUE_H

285
lib/list/list.cpp Normal file
View File

@@ -0,0 +1,285 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "list.h"
void list_init(List_t *list) {
list->head = NULL;
list->tail = NULL;
list->len = 0;
}
bool list_is_empty(List_t *list) {
return (list->head == NULL);
}
static struct List_Node_t *make_node(void *data) //把用户传递过来的数据打包为一个链表节点
{
struct List_Node_t *n;
n = (struct List_Node_t *) malloc(sizeof(struct List_Node_t));
assert(n != NULL);
n->next = NULL;
n->data = data;
return n;
}
void list_insert_at_head(List_t *list, void *data) //头插法
{
struct List_Node_t *n;
n = make_node(data);
if (list->head == NULL) { //如果是空链表
list->head = n;
list->tail = n;
} else { //如果不是非空链表
n->next = list->head;
list->head = n;
}
list->len++;
}
void list_insert_at_index(List_t *list, void *data, long index) //定插法
{
long i = 1; //从1开始算
struct List_Node_t *p, *n;
p = list->head;
while (p && i < index) {
p = p->next;
i++;
}
if (p) { //如果链表遍历完了计数i还没到index说明第index个节点不存在。
n = make_node(data);
n->next = p->next;
p->next = n;
list->len++;
}
}
void list_insert_at_tail(List_t *list, void *data) //尾插法
{
struct List_Node_t *n;
n = make_node(data);
if (list_is_empty(list)) { //如果是空链表
list->head = n;
list->tail = n;
} else { //如果不是非空链表
list->tail->next = n;
list->tail = n;
}
list->len++;
}
//void list_insert(List_t *list, void *data) //默认采用尾插法
//{
//#if 0
// list_insert_at_tail(list, data);
//#else
// struct List_Node_t *n;
// n = make_node(data);
// if(list->head == NULL){
// list->head = n;
// list->tail = n;
// } else {
// list->tail->next = n;
// list->tail = n;
// }
// list->len++;
//#endif
//}
void list_insert(List_t *list, void *data) {
struct List_Node_t *n;
n = make_node(data);
if (list->head == NULL) {
list->head = n;
list->tail = n;
} else {
list->tail->next = n;
list->tail = n;
}
list->len++;
}
void *list_delete(List_t *list, void *key, int (*compare)(const void *, const void *)) {
void *data;
struct List_Node_t *n, *t;
n = list->head;
if (!compare(n->data, key)) { //如果要删除的节点为首节点
t = n;
data = n->data;
list->head = n->next;
free(t);
list->len--;
return data;
}
while (n->next != NULL) { //遍历查找符合条件的节点,删除之
if (compare(n->next->data, key) == 0) { //只删除第一个符合条件的节点。
t = n->next;
if (n->next == list->tail) {
list->tail = n;
}
n->next = n->next->next;
data = t->data;
free(t);
list->len--;
return data; //把删除的数据返回给用户,供用户后续的处理使用。
}
n = n->next;
}
return NULL; //没找到匹配的节点返回NULL
}
void *list_search(List_t *list, void *key, int (*compare)(const void *, const void *)) {
struct List_Node_t *n;
n = list->head;
while (n) {
if (!compare(n->data, key)) { //找到了,返回找到的数据
return n->data;
}
n = n->next;
}
return NULL; //找不到返回NULL
}
static struct List_Node_t *find_min_node(List_t *list,
int (*compare)(const void *, const void *)) {
struct List_Node_t *min, *n;
n = list->head;
min = list->head;
while (n) {
if (compare(min->data, n->data) > 0) {
min = n;
}
n = n->next;
}
return min;
}
static void delete_node(List_t *list, struct List_Node_t *key) {
struct List_Node_t *n;
n = list->head;
if (n == key) {
list->head = n->next;
return;
}
while (n->next) {
if (n->next == key) {
if (key == list->tail) {
list->tail = n;
}
n->next = n->next->next;
return;
}
n = n->next;
}
}
static void insert_node(List_t *list, struct List_Node_t *key) {
if (list->head == NULL) {
list->head = key;
list->tail = key;
} else {
list->tail->next = key;
list->tail = key;
}
}
void list_sort(List_t *list,
int (*compare)(const void *, const void *)) {
List_t tmp;
struct List_Node_t *n;
list_init(&tmp);
while (!list_is_empty(list)) {
n = find_min_node(list, compare);
delete_node(list, n);
n->next = NULL;
insert_node(&tmp, n);
}
list->head = tmp.head;
list->tail = tmp.tail;
}
void list_traverse(List_t *list, void (*handle)(void *)) {
struct List_Node_t *p;
p = list->head;
while (p) {
handle(p->data);
p = p->next;
}
}
void list_reverse(List_t *list) {
struct List_Node_t *pre = NULL, *next, *p = list->head;
list->tail = list->head; //tail指向head
while (p) {
next = p->next;
if (!next) { //当p->next为最后一个节点时让head指向p->next
list->head = p;
}
//记录当前节点为pre作为下一个节点的next.第一个节点为NULL初始化时已定义。
p->next = pre;
pre = p;
p = next;
}
}
long list_get_lenth(List_t *list) {
return (list->len);
}
void *list_get_element(List_t *list, int idx) {
int i = 1;
struct List_Node_t *n;
n = list->head;
while (n && i < idx) {
i++;
n = n->next;
}
if (n) {
return n->data;
}
return NULL;
}
void list_destroy(List_t *list, void (*destroy)(void *)) {
list->len = 0;
struct List_Node_t *n, *t;
n = list->head;
while (n) {
t = n->next; //t只起一个记录n->next的功能否则后面把n free掉之后就找不到n->next了。
if (destroy) { //传递用户自定义的数据处理函数为0时不执行
destroy(n->data); //使用用户提供的destroy函数来释放用户传递过来的数据。
}
free(n);
n = t; //把n free掉之后再把t给n相当于把n->next给n,如此循环遍历链表,挨个删除,
}
}

145
lib/list/queue.cpp Normal file
View File

@@ -0,0 +1,145 @@
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <cstdio>
#include "queue.h"
static Queue_Node_t *newQueue_Node_t(void *data, unsigned char size) {
Queue_Node_t *node = (Queue_Node_t *) malloc(sizeof(Queue_Node_t));
node->val = malloc(size);
node->next = NULL;
node->prev = NULL;
if (node->val == NULL) {
printf("Error allocating memory");
return NULL;
}
memcpy(node->val, data, size);
return node;
}
/* 析构函数 */
static void delQueue_Node_t(Queue_Node_t *node) {
free(node->val);
free(node);
}
/* 构造函数 */
Queue_List_t *newQueue_List(unsigned char size) {
Queue_List_t *deque = (Queue_List_t *) malloc(sizeof(Queue_List_t));
deque->front = NULL;
deque->rear = NULL;
deque->queSize = 0;
deque->typeSize = size;
return deque;
}
/* 析构函数 */
void delQueue_List(Queue_List_t *deque) {
// 释放所有节点
for (int i = 0; i < deque->queSize && deque->front != NULL; i++) {
Queue_Node_t *tmp = deque->front;
deque->front = deque->front->next;
delQueue_Node_t(tmp);
}
// 释放 deque 结构体
free(deque);
}
/* 获取队列的长度 */
int queue_size(Queue_List_t *deque) {
return deque->queSize;
}
/* 判断队列是否为空 */
bool queue_is_empty(Queue_List_t *deque) {
return (queue_size(deque) == 0);
}
/* 入队 */
static void push(Queue_List_t *deque, void *data, bool isFront) {
Queue_Node_t *node = newQueue_Node_t(data, deque->typeSize);
if (node == NULL) {
printf("Error creating new node");
return;
}
if (queue_is_empty(deque)) {
deque->front = deque->rear = node;
} else if (isFront) {
deque->front->prev = node;
node->next = deque->front;
deque->front = node;
} else {
deque->rear->next = node;
node->prev = deque->rear;
deque->rear = node;
}
deque->queSize++;
}
/* 队首入队 */
void pushFirst(Queue_List_t *deque, void *data) {
push(deque, data, true);
}
/* 队尾入队 */
void pushLast(Queue_List_t *deque, void *data) {
push(deque, data, false);
}
/* 访问队首元素 */
void *peekFirst(Queue_List_t *deque) {
assert(queue_size(deque) && deque->front);
return deque->front->val;
}
/* 访问队尾元素 */
void *peekLast(Queue_List_t *deque) {
assert(queue_size(deque) && deque->rear);
return deque->rear->val;
}
/* 出队 */
static void *pop(Queue_List_t *deque, bool isFront) {
if (queue_is_empty(deque))
return NULL;
void *val = malloc(deque->typeSize);
if (val == nullptr) {
printf("Error allocating memory");
return NULL;
}
if (isFront) {
memcpy(val, deque->front->val, deque->typeSize);
Queue_Node_t *fNext = deque->front->next;
if (fNext) {
fNext->prev = NULL;
deque->front->next = NULL;
}
delQueue_Node_t(deque->front);
deque->front = fNext;
} else {
memcpy(val, deque->rear->val, deque->typeSize);
Queue_Node_t *rPrev = deque->rear->prev;
if (rPrev) {
rPrev->next = NULL;
deque->rear->prev = NULL;
}
delQueue_Node_t(deque->rear);
deque->rear = rPrev;
}
deque->queSize--;
return val;
}
/* 队首出队 */
void *popFirst(Queue_List_t *deque) {
return pop(deque, true);
}
/* 队尾出队 */
void *popLast(Queue_List_t *deque) {
return pop(deque, false);
}