C语言|数据结构

一、顺序表:详细见内存管理

二、链表

// 单链表节点定义(LeetCode标准)
typedef struct ListNode {
    int val;
    struct ListNode *next;
} ListNode;

// 创建新节点
ListNode* createNode(int val) {
    ListNode *node = (ListNode *)malloc(sizeof(ListNode));
    node->val = val;
    node->next = NULL;
    return node;
}

// 链表反转(高频中的高频)
ListNode* reverseList(ListNode *head) {
    ListNode *pre = NULL, *cur = head, *next = NULL;
    while (cur != NULL) {
        next = cur->next; // 保存下一个节点
        cur->next = pre;  // 反转指针
        pre = cur;        // 移动pre
        cur = next;       // 移动cur
    }
    return pre; // 新头节点
}

// 链表查找指定值节点
ListNode* findNode(ListNode *head, int val) {
    while (head != NULL) {
        if (head->val == val) return head;
        head = head->next;
    }
    return NULL;
}

三、栈

// 栈结构定义
#define MAX_STACK_SIZE 10000 // 适配LeetCode数据范围
typedef struct {
    int data[MAX_STACK_SIZE];
    int top; // 栈顶指针(初始-1)
} Stack;

// 初始化栈
void stackInit(Stack *stack) {
    stack->top = -1;
}

// 判断栈空
int stackIsEmpty(Stack *stack) {
    return stack->top == -1;
}

// 入栈
int stackPush(Stack *stack, int val) {
    if (stack->top >= MAX_STACK_SIZE - 1) return 0; // 栈满
    stack->data[++stack->top] = val;
    return 1;
}

// 出栈
int stackPop(Stack *stack, int *val) {
    if (stackIsEmpty(stack)) return 0;
    *val = stack->data[stack->top--];
    return 1;
}

// 获取栈顶元素
int stackPeek(Stack *stack, int *val) {
    if (stackIsEmpty(stack)) return 0;
    *val = stack->data[stack->top];
    return 1;
}

四、队列

// 循环队列结构定义
#define MAX_QUEUE_SIZE 10000
typedef struct {
    int data[MAX_QUEUE_SIZE];
    int front; // 队头指针
    int rear;  // 队尾指针(指向下一个可插入位置)
} Queue;

// 初始化队列
void queueInit(Queue *queue) {
    queue->front = 0;
    queue->rear = 0;
}

// 判断队列空
int queueIsEmpty(Queue *queue) {
    return queue->front == queue->rear;
}

// 判断队列满
int queueIsFull(Queue *queue) {
    return (queue->rear + 1) % MAX_QUEUE_SIZE == queue->front;
}

// 入队
int queueEnqueue(Queue *queue, int val) {
    if (queueIsFull(queue)) return 0;
    queue->data[queue->rear] = val;
    queue->rear = (queue->rear + 1) % MAX_QUEUE_SIZE;
    return 1;
}

// 出队
int queueDequeue(Queue *queue, int *val) {
    if (queueIsEmpty(queue)) return 0;
    *val = queue->data[queue->front];
    queue->front = (queue->front + 1) % MAX_QUEUE_SIZE;
    return 1;
}

五、二叉树

// 二叉树节点定义(LeetCode标准)
typedef struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
} TreeNode;

// 创建二叉树节点
TreeNode* createTreeNode(int val) {
    TreeNode *node = (TreeNode *)malloc(sizeof(TreeNode));
    node->val = val;
    node->left = NULL;
    node->right = NULL;
    return node;
}

// 二叉树前序遍历(递归版,简洁)
void preOrder(TreeNode *root) {
    if (root == NULL) return;
    printf("%d ", root->val); // 访问节点(刷题时替换为业务逻辑)
    preOrder(root->left);
    preOrder(root->right);
}

// 二叉树层序遍历(BFS,高频)
void levelOrder(TreeNode *root) {
    if (root == NULL) return;
    Queue queue;
    queueInit(&queue);
    queueEnqueue(&queue, (int)(long long)root); // 指针转int存储
    while (!queueIsEmpty(&queue)) {
        int val;
        queueDequeue(&queue, &val);
        TreeNode *node = (TreeNode *)(long long)val;
        printf("%d ", node->val); // 访问节点
        if (node->left != NULL) queueEnqueue(&queue, (int)(long long)node->left);
        if (node->right != NULL) queueEnqueue(&queue, (int)(long long)node->right);
    }
}

六、哈希表

// 哈希表节点
typedef struct HashNode {
    int key;
    int val;
    struct HashNode *next;
} HashNode;

// 哈希表结构(链地址法解决冲突)
#define HASH_SIZE 1009 // 质数,减少冲突
typedef struct {
    HashNode *table[HASH_SIZE];
} HashTable;

// 哈希函数
int hashFunc(int key) {
    return abs(key) % HASH_SIZE;
}

// 初始化哈希表
void hashInit(HashTable *ht) {
    for (int i = 0; i < HASH_SIZE; i++) {
        ht->table[i] = NULL;
    }
}

// 插入键值对
void hashInsert(HashTable *ht, int key, int val) {
    int idx = hashFunc(key);
    HashNode *node = (HashNode *)malloc(sizeof(HashNode));
    node->key = key;
    node->val = val;
    node->next = ht->table[idx]; // 头插法
    ht->table[idx] = node;
}

// 查找key对应的val(找不到返回-1)
int hashFind(HashTable *ht, int key) {
    int idx = hashFunc(key);
    HashNode *cur = ht->table[idx];
    while (cur != NULL) {
        if (cur->key == key) return cur->val;
        cur = cur->next;
    }
    return -1;
}

// 释放哈希表内存(刷题可选,避免内存泄漏)
void hashFree(HashTable *ht) {
    for (int i = 0; i < HASH_SIZE; i++) {
        HashNode *cur = ht->table[i];
        while (cur != NULL) {
            HashNode *temp = cur;
            cur = cur->next;
            free(temp);
        }
        ht->table[i] = NULL;
    }
}

七、双向链表

// 双向链表节点定义
typedef struct DListNode {
    int key;          // 存key(LRU需删除尾节点时同步删哈希表)
    int val;          // 存值
    struct DListNode *prev;
    struct DListNode *next;
} DListNode;

// 双向链表结构(带哨兵头/尾,简化边界处理)
typedef struct {
    DListNode *head;  // 哨兵头节点
    DListNode *tail;  // 哨兵尾节点
    int size;         // 链表长度
} DLinkedList;

// 创建双向链表节点
DListNode* createDListNode(int key, int val) {
    DListNode *node = (DListNode*)malloc(sizeof(DListNode));
    node->key = key;
    node->val = val;
    node->prev = NULL;
    node->next = NULL;
    return node;
}

// 初始化双向链表(哨兵头尾相连)
DLinkedList* initDLinkedList() {
    DLinkedList *list = (DLinkedList*)malloc(sizeof(DLinkedList));
    list->head = createDListNode(-1, -1);
    list->tail = createDListNode(-1, -1);
    list->head->next = list->tail;
    list->tail->prev = list->head;
    list->size = 0;
    return list;
}

// 将节点插入到链表头部(LRU访问后移到头部)
void addToHead(DLinkedList *list, DListNode *node) {
    node->prev = list->head;
    node->next = list->head->next;
    list->head->next->prev = node;
    list->head->next = node;
    list->size++;
}

// 删除指定节点(无需遍历找前驱/后继)
void removeNode(DLinkedList *list, DListNode *node) {
    node->prev->next = node->next;
    node->next->prev = node->prev;
    list->size--;
}

// 删除并返回尾节点(LRU满时删除尾节点)
DListNode* removeTail(DLinkedList *list) {
    DListNode *tailNode = list->tail->prev;
    removeNode(list, tailNode);
    return tailNode;
}

八、优先级队列

// 优先级队列元素(存值+优先级,这里用值本身作为优先级)
typedef struct {
    int *data;       // 堆数组
    int capacity;    // 容量
    int size;        // 当前元素数
} PriorityQueue;

// 初始化优先级队列(小顶堆,可改比较逻辑为大顶堆)
PriorityQueue* initPriorityQueue(int capacity) {
    PriorityQueue *pq = (PriorityQueue*)malloc(sizeof(PriorityQueue));
    pq->data = (int*)malloc((capacity + 1) * sizeof(int)); // 堆从1开始存储
    pq->capacity = capacity;
    pq->size = 0;
    return pq;
}

// 交换堆中两个元素
void swapPq(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

// 小顶堆下沉调整(核心)
void heapifyDown(PriorityQueue *pq, int idx) {
    int minIdx = idx;
    int left = 2 * idx;   // 左子节点
    int right = 2 * idx + 1; // 右子节点
    // 找最小的子节点
    if (left <= pq->size && pq->data[left] < pq->data[minIdx]) minIdx = left;
    if (right <= pq->size && pq->data[right] < pq->data[minIdx]) minIdx = right;
    if (minIdx != idx) {
        swapPq(&pq->data[idx], &pq->data[minIdx]);
        heapifyDown(pq, minIdx); // 递归调整
    }
}

// 小顶堆上浮调整
void heapifyUp(PriorityQueue *pq, int idx) {
    while (idx > 1 && pq->data[idx / 2] > pq->data[idx]) {
        swapPq(&pq->data[idx / 2], &pq->data[idx]);
        idx /= 2;
    }
}

// 入队(插入元素)
int pqEnqueue(PriorityQueue *pq, int val) {
    if (pq->size >= pq->capacity) return 0; // 队列满
    pq->size++;
    pq->data[pq->size] = val;
    heapifyUp(pq, pq->size); // 上浮调整
    return 1;
}

// 出队(弹出优先级最高的元素,小顶堆即最小值)
int pqDequeue(PriorityQueue *pq, int *val) {
    if (pq->size == 0) return 0; // 队列空
    *val = pq->data[1];
    pq->data[1] = pq->data[pq->size]; // 最后一个元素移到堆顶
    pq->size--;
    heapifyDown(pq, 1); // 下沉调整
    return 1;
}

// 获取队首元素(不弹出)
int pqPeek(PriorityQueue *pq, int *val) {
    if (pq->size == 0) return 0;
    *val = pq->data[1];
    return 1;
}

九、并查集

// 并查集结构
typedef struct {
    int *parent; // 父节点数组
    int *rank;   // 秩(用于按秩合并,减少树高度)
    int count;   // 连通分量数
} UnionFind;

// 初始化并查集
UnionFind* initUnionFind(int n) {
    UnionFind *uf = (UnionFind*)malloc(sizeof(UnionFind));
    uf->parent = (int*)malloc(n * sizeof(int));
    uf->rank = (int*)malloc(n * sizeof(int));
    uf->count = n; // 初始每个元素自成一个集合
    for (int i = 0; i < n; i++) {
        uf->parent[i] = i; // 父节点指向自己
        uf->rank[i] = 1;   // 初始秩为1
    }
    return uf;
}

// 查找根节点(路径压缩,降低查找复杂度)
int find(UnionFind *uf, int x) {
    if (uf->parent[x] != x) {
        uf->parent[x] = find(uf, uf->parent[x]); // 路径压缩
    }
    return uf->parent[x];
}

// 合并两个集合(按秩合并,避免树退化成链表)
void unionSet(UnionFind *uf, int x, int y) {
    int rootX = find(uf, x);
    int rootY = find(uf, y);
    if (rootX == rootY) return; // 已在同一集合
    
    // 秩小的树合并到秩大的树下
    if (uf->rank[rootX] < uf->rank[rootY]) {
        uf->parent[rootX] = rootY;
    } else if (uf->rank[rootX] > uf->rank[rootY]) {
        uf->parent[rootY] = rootX;
    } else {
        uf->parent[rootY] = rootX;
        uf->rank[rootX]++; // 秩相同,合并后秩+1
    }
    uf->count--; // 连通分量数减1
}

// 判断两个元素是否连通
int isConnected(UnionFind *uf, int x, int y) {
    return find(uf, x) == find(uf, y);
}

十、邻接表

// 邻接表节点(存储邻接顶点+权重,无权图权重可设为1)
typedef struct AdjNode {
    int vertex;      // 邻接顶点索引
    int weight;      // 边权重
    struct AdjNode *next;
} AdjNode;

// 邻接表头(每个顶点对应一个链表)
typedef struct AdjList {
    AdjNode *head;
} AdjList;

// 图结构(邻接表实现)
typedef struct {
    int numVertices; // 顶点数
    AdjList *array;  // 邻接表数组
    int isDirected;  // 是否有向图(1:有向,0:无向)
} Graph;

// 创建邻接表节点
AdjNode* createAdjNode(int v, int weight) {
    AdjNode *node = (AdjNode*)malloc(sizeof(AdjNode));
    node->vertex = v;
    node->weight = weight;
    node->next = NULL;
    return node;
}

// 初始化图
Graph* initGraph(int vertices, int isDirected) {
    Graph *graph = (Graph*)malloc(sizeof(Graph));
    graph->numVertices = vertices;
    graph->isDirected = isDirected;
    graph->array = (AdjList*)malloc(vertices * sizeof(AdjList));
    // 初始化每个顶点的邻接表为空
    for (int i = 0; i < vertices; i++) {
        graph->array[i].head = NULL;
    }
    return graph;
}

// 添加边(无向图需添加双向边)
void addEdge(Graph *graph, int src, int dest, int weight) {
    // 添加src→dest的边
    AdjNode *node = createAdjNode(dest, weight);
    node->next = graph->array[src].head;
    graph->array[src].head = node;
    // 无向图需添加dest→src的边
    if (!graph->isDirected) {
        node = createAdjNode(src, weight);
        node->next = graph->array[dest].head;
        graph->array[dest].head = node;
    }
}

// 图的DFS遍历(递归版)
void dfsGraph(Graph *graph, int v, int *visited) {
    visited[v] = 1; // 标记已访问
    printf("访问顶点:%d ", v); // 刷题时替换为业务逻辑
    
    AdjNode *cur = graph->array[v].head;
    while (cur != NULL) {
        if (!visited[cur->vertex]) {
            dfsGraph(graph, cur->vertex, visited);
        }
        cur = cur->next;
    }
}

十一、单调栈

// 单调栈(基于之前的栈结构,封装单调逻辑)
#define MAX_MONO_STACK_SIZE 10000
typedef struct {
int data[MAX_MONO_STACK_SIZE];
int top;
} MonoStack;

// 初始化单调栈
void monoStackInit(MonoStack *stack) {
stack->top = -1;
}

// 判断栈空
int monoStackIsEmpty(MonoStack *stack) {
return stack->top == -1;
}

// 入栈(保持栈内元素单调递减,可改逻辑为递增)
int monoStackPush(MonoStack *stack, int val) {
if (stack->top >= MAX_MONO_STACK_SIZE - 1) return 0;
// 弹出所有比当前值小的元素(单调递减栈)
while (!monoStackIsEmpty(stack) && stack->data[stack->top] < val) {
stack->top--;
}
stack->data[++stack->top] = val;
return 1;
}

// 出栈(仅弹出栈顶,不处理单调逻辑)
int monoStackPop(MonoStack *stack, int *val) {
if (monoStackIsEmpty(stack)) return 0;
*val = stack->data[stack->top--];
return 1;
}

// 示例:找数组中每个元素的下一个更大元素(LeetCode 496题)
int* nextGreaterElement(int nums[], int n, int *resSize) {
*resSize = n;
int *res = (int*)malloc(n * sizeof(int));
MonoStack stack;
monoStackInit(&stack);

// 倒序遍历
for (int i = n - 1; i >= 0; i--) {
// 弹出栈中比当前元素小的
while (!monoStackIsEmpty(&stack) && stack.data[stack.top] <= nums[i]) {
stack.top--;
}
// 栈空则无更大元素,否则栈顶是答案
res[i] = monoStackIsEmpty(&stack) ? -1 : stack.data[stack.top];
// 当前元素入栈
stack.data[++stack.top] = nums[i];
}
return res;
}

发表评论