C语言数据结构编写练习

主函数

main.c

#include <malloc.h>
#include "main.h"
#include <stdio.h>

#ifdef selector
#if(selector < tree_1)
#include "SeqList.h"
void SeqList();
#elif(selector < hash_1)
#include "Tree.h"
void Tree();
#elif(selector < graph_1)
#include "Hash.h"
void Hash();
#elif(selector < sort_1)
#include "Graph.h"
void Graph();
#else
#include "Sort.h"
void Sort();
#endif
#else
#include "BinarySearch.h"
#endif

int main()
{
/***********************************************************************************
 *                                   Catalog                                       *
 ***********************************************************************************\ <br>
 * 1. 线性表<br>
 *  1.1 顺序表<br>
 *  1.2 链表<br>
 *   1.2.1 双向链表<br>
 *   1.2.2 循环链表<br>
 *  1.3 栈<br>
 *  1.4 队列<br>
 ***********************************************************************************\
 * 2. 树<br>
 *  2.1 二叉树<br>
 *   2.1.1 线索化二叉树<br>
 *   2.1.2 二叉查找树<br>
 *   2.1.3 平衡二叉树 AVL<br>
 *  2.2 红黑树<br>
 *  2.3 B树 & B+树<br>
 *  2.4 哈夫曼树<br>
 *  2.5 堆和优先队列<br>
 ***********************************************************************************\
 * 3. 散列表<br>
 *  3.1 哈希函数 & 哈希表<br>
 *  *冲突解决*:<br>
 *   3.1.1 线性探测法<br>
 *   3.1.2 链地址法<br>
 ***********************************************************************************\
 * 4. 图<br>
 *  4.1 邻接矩阵<br>
 *  4.2 邻接表<br>
 *  4.3 深度优先DFS<br>
 *  4.4 广度优先BFS<br>
 *  4.5 生成树 & 最小生成树<br>
 *  4.6 单源最短路径 & 顶点最短路径<br>
 *  4.7 拓扑排序<br>
 *  4.8 关键路径<br>
 ***********************************************************************************\
 * 5. 排序<br>
 *  5.1 冒泡<br>
 *  5.2 插入<br>
 *  5.3 选择<br>
 *  5.4 快排<br>
 *  5.5 希尔<br>
 *  5.6 堆<br>
 *  5.7 归并<br>
 *  5.8 计数<br>
 *  5.9 桶<br>
 *  5.10 基数<br>
 ***********************************************************************************/
#ifdef selector
#if(selector < tree_1)
//#include "SeqList.h"
    SeqList();
#elif(selector < hash_1)
    Tree();
#elif(selector < graph_1)
    Hash();
#elif(selector < sort_1)
    Graph();
#else
    Sort();
#endif
#else
    /** 0. 二分法 */
    int arr[] =  {1, 2, 3, 4, 5, 6, 7, 8, 9}, target = 3;
    printf("target id %d", binarySearch(arr, 9, target));
#endif
    return 0;
}

/**
 * @fun:   SeqList
 * @data:  2022/9/17
 * @brief: 主函数线性表
 * @param: None
 * @ret:   None
 */
void SeqList()
{
    /**
     * 1. 线性表<br>
     *  1.1 顺序表<br>
     *  1.2 链表<br>
     *   1.2.1 双向链表<br>
     *   1.2.2 循环链表<br>
     *  1.3 栈<br>
     *  1.4 队列<br>
     */
#if(selector == seqList_1)
    /** 1.1 顺序表
     * 适合查找
     */
    List list;
    seqList_build(&list, 3);
    seqList_push(&list, 1);
    seqList_destroy(&list);
#elif (selector == seqList_2)
    /** 1.2 链表
     * 插入(好于顺序表)、删除、获取元素的时间复杂度 O(n), 适合频繁写入
     */
    ListNode head;
    linkList_create(&head);
    for (int i = 1; i <= 4; i++) {
        linkList_add(&head, i, i*1);
    }
    linkList_iterate(&head);
    linkList_delete(&head, 5);
    linkList_iterate(&head);
    linkList_delete(&head, 1);
    printf("index for : %d\r\n", linkList_search(&head, 4));
    printf("index for : %d\r\n", linkList_search(&head, 2));
    printf("index for : %d\r\n", linkList_search(&head, 6));
    printf("index of %d\r\n", linkList_retrieve(&head, 2));
    printf("index of %d\r\n", linkList_retrieve(&head, 5));
    printf("index of %d\r\n", linkList_retrieve(&head, 1));
    printf("length: %d", linkList_length(&head));
#elif (selector == seqList_2_1)
    /** 1.2.1 双向链表 */
    struct doubleListNode_t head;
    dLinkList_init(&head);
    for (int i = 1; i <= 4; i++)
    {
        dLinkList_insert(&head, i, i*1);
    }
    dLinkList_show(&head);
    dLinkList_destroy(&head, 5);
    dLinkList_show(&head);
    dLinkList_destroy(&head, 4);
    dLinkList_show(&head);
    dLinkList_destroy(&head, 1);
    dLinkList_show(&head);

#elif (selector == seqList_2_2)
    /** 1.2.2 循环链表 */
    struct cycleLinkList_t head;
    cLinkList_born(&head);
    for (int i = 1; i <= 4; i++)
    {
        cLinkList_join(&head, i, i*1);
    }
    cLinkList_scan(&head);
    // 循环链表末尾节点指向头节点(未存放数据), 故而索引从1开始
    // 无需考虑删除头结点,重新建链的情况
    cLinkList_kick(&head, 1);
    cLinkList_scan(&head);
    // 删除最后一个节点(注前面已删除1个)
    cLinkList_kick(&head, 3);
    cLinkList_scan(&head);

#elif (selector == seqList_3)
    /** 1.3 栈 */
    // 见 seqList
    ShareStack stack;
    stack->capacity = 3;
    stack->arr = malloc(sizeof(E) * stack->capacity);
    stack->leftTop = 0;
    stack->rightTop = stack->capacity - 1;

    pushShareStack(stack, 1, 0);
    pushShareStack(stack, 3, 1);
    pushShareStack(stack, 2, 1);
    pushShareStack(stack, 4, 1);
//    printf("%d %d \r\n", stack->leftTop, stack->rightTop);
    for (int i = 0; i < stack->capacity; i++)
        printf("%d ", stack->arr[i]);
    printf("\r\n");

    printf("%d ", popShareStack(stack, 0));
    printf("%d ", popShareStack(stack, 0));
    printf("%d ", popShareStack(stack, 1));
    printf("%d ", popShareStack(stack, 1));
#elif (selector == seqList_4)
    /** 1.4 队列 */
    // 环形
    rQueue queue;
//    struct RingQueue_t queue;
    rQueueInit(queue, 3);
//    for (int i = 0; i < 3; i++) // 超出
    for (int i = 0; i < 2; i++)
    {
        if (isFull(queue)) break;
        inRQueue(queue, i);
    }
    rQueueIter(queue);
    if(!isEmpty(queue))
    {
        printf("%d ", outRQueue(queue));
    }


    // 链式
    QueueLink queueL;
    QueueLinkNodeInit(queueL);
    for (int i = 0; i < 5; i++)
    {
        inQueueLinkNode(queueL, i * 10);
    }
    QueueLinkNodeItr(queueL);
    for (int i = 0; i < 6; i++)
        printf("%d ", outQueueLinkNode(queueL));
    QueueLinkNodeItr(queueL);

#endif
}

/**
 * @fun:   Tree
 * @data:  2022/9/17
 * @brief: 主函数树结构
 * @param: None
 * @ret:   None
 */
void Tree()
{
    /**
     * 2. 树<br>
     *  2.1 二叉树<br>
     *   2.1.1 线索化二叉树<br>
     *   2.1.2 二叉查找树<br>
     *   2.1.3 平衡二叉树 AVL<br>
     *  2.2 红黑树<br>
     *  2.3 B树 & B+树<br>
     *  2.4 哈夫曼树<br>
     *  2.5 堆和优先队列<br>
     */
#if(selector == tree_1)
    /** 2.1 二叉树 */
    BinaryTree root, leftNode, rightNode;
    //      A
    //    B   C
    //  D
    leftNode = BinaryTreeBuild(NULL, NULL, 'D');
    leftNode = BinaryTreeBuild(leftNode, NULL, 'B');
    rightNode = BinaryTreeBuild(NULL, NULL, 'C');
    root = BinaryTreeBuild(leftNode, rightNode, 'A');

    printf("%c ", root->elem);
    printf("%c ", root->leftChild->elem);
    printf("%c ", root->rightChild->elem);
    // 前序
    BinaryTreePreOrderTraversal(root);
    printf("\n");
    BinaryTreePreOrder(root);
    printf("\n");
    // 中序
    BinaryTreeInorderTraversal(root);
    printf("\n");
    BinaryTreeInorder(root);
    printf("\n");
    // 后序
    BinaryTreePostOrderTraversal(root);
    printf("\n");
    BinaryTreePostOrder(root);
    printf("\n");
    // 层序
    BinaryTreeLevelOrder(root);
    printf("\n");
#elif(selector == tree_1_1)
    /** 2.1.1 线索化二叉树 */
    // 左节点指向父节点, 右节点指向父节点的后继节点
#elif(selector == tree_1_2)
    /** 2.1.2 二叉查找树 */

#elif(selector == tree_1_3)
    /** 2.1.3 平衡二叉树 */
    Node root = NULL;
    int i = 0;
    while(i < 20)
    {
        I e;
        scanf("%d", &e);
        root = insert(root, e);
        i++;
    }
    /** 红黑树 */

#elif(selector == tree_2)
    /** 2.2 B树 & B+树 */
#elif(selector == tree_3)
    /** 2.3 哈夫曼树 */
    const int size = 5;
    char alpha[] = {'A', 'B', 'C', 'D', 'E'};
    int weights[] = {1, 11, 3, 6, 2};
    HuffmanTree root;
    root = buildHuffmanTree(alpha, weights, size);
    for (int i = 0; i < size; i++)
    {
        printf("%s\r\n", encoder(root, alpha[i]));
    }
//    printf("%s\r\n", encoder(root, 'B'));
//    printf("%s\r\n", encoder(root, 'C'));
//    printf("%s\r\n", encoder(root, 'D'));
//    printf("%s\r\n", encoder(root, 'D'));
//    printf("%s\r\n", encoder(root, 'E'));

#elif(selector == tree_4)
    /** 2.4 堆和优先队列 */
    struct MaxHeap heap;
    initHeap(&heap);
    insert(&heap, 0);
    insert(&heap, 10);
    insert(&heap, 4);
    insert(&heap, 9);
    insert(&heap, 3);
    print(&heap);
    delete(&heap);
    print(&heap);

#endif
}

/**
 * @fun:   Hash
 * @data:  2022/9/17
 * @brief: 主函数散列表
 * @param: None
 * @ret:   None
 */
void Hash()
{
/**
 * 3. 散列表<br>
 *  3.1 哈希函数 & 哈希表<br>
 *  冲突解决:<br>
 *   3.1.1 线性探测法<br>
 *   3.1.2 链地址法<br>
 */
#if(selector == hash_1)
    /** 3.1 哈希函数 & 哈希表 */
    struct HashTable_t table;
    initHash(&table);
    insertHash(&table, createElement(0));
    insertHash(&table, createElement(10));
    insertHash(&table, createElement(70));
    insertHash(&table, createElement(54));

    printf("%d %d ", searchHash(&table, 54), searchHash(&table, 5));
//#elif(selector == hash_1_1)
    /** 3.1.1 线性探测法 */
    insertHash_LD(&table, createElement(154));
    printf("%d %d ", searchHash_LD(&table, 154), searchHash_LD(&table, 54));
#elif(selector == hash_1_2)
    /** 3.1.2 链地址法 */
    struct HashTable hashTable;
    initHashTable(&hashTable);
    insertHash(&hashTable, 10);
    insertHash(&hashTable, 20);
    insertHash(&hashTable, 1);

    printf("%d %d %d %d", searchHash(&hashTable, 10), searchHash(&hashTable, 20),
           searchHash(&hashTable, 1), searchHash(&hashTable, 2));
#endif

}

/**
 * @fun:   Graph
 * @data:  2022/9/17
 * @brief: 主函数图结构
 * @param: None
 * @ret:   None
 */
void Graph()
{
/**
 * 4. 图<br>
 *  4.1 邻接矩阵<br>
 *  4.2 邻接表<br>
 *  4.3 深度优先<br>
 *  4.4 广度优先<br>
 *  4.5 生成树 & 最小生成树<br>
 *  4.6 单源最短路径 & 顶点最短路径<br>
 *  4.7 拓扑排序<br>
 *  4.8 关键路径<br>
 */
#if (selector == graph_1)
    /** 4.1 邻接矩阵 */
    MatrixGraph graph = create();
    for (int c = 'A'; c <= 'D' ; ++c)
        addVertex(graph, (char) c);
    addEdge(graph, 0, 1);   //A -> B
    addEdge(graph, 1, 2);   //B -> C
    addEdge(graph, 2, 3);   //C -> D
    addEdge(graph, 3, 0);   //D -> A
    addEdge(graph, 2, 0);   //C -> A
    printGraph(graph);
#elif (selector == graph_2)
    /** 4.2 邻接表 */
    AdjacencyGraph graph = create();
    for (int c = 'A'; c <= 'D' ; ++c)
        addVertex(graph, (char) c);
    addEdge(graph, 0, 1);   //A -> B
    addEdge(graph, 1, 2);   //B -> C
    addEdge(graph, 2, 3);   //C -> D
    addEdge(graph, 3, 0);   //D -> A
    addEdge(graph, 2, 0);   //C -> A

    printGraph(graph);
#elif (selector == graph_3)
    /** 4.3 深度优先 */
    AdjacencyGraph graph = create();
    for (int c = 'A'; c <= 'F' ; ++c)
        addVertex(graph, (char) c);
    addEdge(graph, 0, 1);   //A -> B
    addEdge(graph, 1, 2);   //B -> C
    addEdge(graph, 1, 3);   //B -> D
    addEdge(graph, 1, 4);   //D -> E
    addEdge(graph, 4, 5);   //E -> F

    printGraph(graph);
    int arr[graph->vertexCount];
    for (int i = 0; i < graph->vertexCount; ++i) arr[i] = 0;
    dfs(graph, 0, 5, arr);
#elif (selector == graph_4)
    /** 4.4 广度优先 */
    AdjacencyGraph graph = create();
    for (int c = 'A'; c <= 'F' ; ++c)
        addVertex(graph, (char) c);
    addEdge(graph, 0, 1);   //A -> B
    addEdge(graph, 1, 2);   //B -> C
    addEdge(graph, 1, 3);   //B -> D
    addEdge(graph, 1, 4);   //D -> E
    addEdge(graph, 4, 5);   //E -> F

    printGraph(graph);
    int arr[graph->vertexCount];
    struct _Queue queue;
    _initQueue(&queue);
    for (int i = 0; i < graph->vertexCount; ++i) arr[i] = 0;
    bfs(graph, 0, 5, arr, &queue);
#elif (selector == graph_5)
    /** 4.5 生成树 & 最小生成树  */

#elif (selector == graph_6)
    /** 4.6 单源最短路径 & 顶点最短路径 */

#elif (selector == graph_7)
    /** 4.7 拓扑排序 */

#elif (selector == graph_8)
    /** 4.8 关键路径 */

#endif
}

/**
 * @fun:   Sort
 * @data:  2022/9/17
 * @brief: 主函数排序
 * @param: None
 * @ret:   None
 */
void Sort()
{
/**
 * 5. 排序<br>
 *  5.1 冒泡<br>
 *  5.2 插入<br>
 *  5.3 选择<br>
 *  5.4 快排<br>
 *  5.5 双轴快排<br>
 *  5.6 希尔<br>
 *  5.7 归并<br>
 *  5.8 计数<br>
 *  5.9 堆<br>
 *  5.10 基数<br>
 */
    int arr[] = {10, 9, 8, 3, 4, 9, 2};
    int size = sizeof(arr)/sizeof(*arr);
#if (selector == sort_1)
    /** 5.1 冒泡  */
    int *res = BubbleSort(arr, size);
#elif (selector == sort_2)
    /** 5.2 插入  */
    int *res = insertSort(arr, size);
#elif (selector == sort_3)
    /** 5.3 选择  */
    int *res = selectSort(arr, size);
#elif (selector == sort_4)
    /** 5.4 快排  */
    int *res = quickSort(arr, 0, size-1);
#elif (selector == sort_5)
    /** 5.5 希尔  */
    int *res = shellSort(arr, size);
#elif (selector == sort_6)
    /** 5.6 堆  */
    struct MinHeap heap;    //先创建堆
    initHeap(&heap, size+1);
    for (int i = 0; i < size; ++i)
        insertHeap(&heap, arr[i]);   //直接把乱序的数组元素挨个插入
    for (int i = 0; i < size; ++i)
        arr[i] = deleteHeap(&heap);    //然后再一个一个拿出来, 就是按顺序的了

    int *res = arr;
#elif (selector == sort_7)
    /** 5.7 归并  */
    int tmp[size];
    int *res = mergeSort(arr, tmp, 0, size - 1);
//    for (int i = 0; i < size; i++) printf("%d ", arr[i]);
#elif (selector == sort_8)
    /** 5.8 计数  */

#elif (selector == sort_9)
    /** 5.9 堆  */

#elif (selector == sort_10)
    /** 5.10 基数  */

#endif
    for (int i = 0; i < size; i++) printf("%d ", res[i]);
}

main.h

#ifndef DATA_STRUCT_MAIN_H
#define DATA_STRUCT_MAIN_H

#include <stdio.h>


/**********************************************************************************
 * 1. 线性表                                                                       *
 **********************************************************************************/
#define seqList_1       110         /** 1.1 顺序表
                                     *      1) 插入、删除 O(n), 搜索 O(1)
                                     *      2) 随机访问
                                     */
#define seqList_2       120         /** 1.2 链表
                                     *      1) 插入、删除、搜索 O(n)
                                     */
#define seqList_2_1     121             /** 1.2.1 双向链表 */
#define seqList_2_2     122             /** 1.2.2 循环链表 */
#define seqList_3       130         /** 1.3 栈 */
#define seqList_4       140         /** 1.4 队列 */

/**********************************************************************************
 * 2. 树                                                                          *
 **********************************************************************************/
#define tree_1          210         /** 2.1 二叉树:
                                     *      1) 第 i 层的最大节点数为 2^{i-1} 个
                                     *      2) 深度为 k 的二叉树, 最大节点数为 n = (2^k) - 1 =  2^0 + ... + 2^{k-1}
                                     *      3) 度为 0, 1, 2 的节点数量分别为 n_0, n_1, n_2
                                     *          节点总数: n = n_0 + n_1 + n_2
                                     *          每个节点有且仅有一条边与其父节点相连, 边数之和: E = n_1 + 2 * n_2 = n - 1
                                     *          则 n = n_1 + 2 * n_2 + 1
                                     *          故而 叶子节点数: n_0 = n_2 + 1
                                     */
#define tree_1_1        211             /** 2.1.1 线索化二叉树
                                         *      1) 节点的左指针,指向其当前遍历顺序的前驱节点
                                         *      2) 节点的右指针,指向其当前遍历顺序的后继节点
                                         */
#define tree_1_2        212             /** 2.1.2 二叉查找树
                                         *      1) 左子树中所有节点的值,均小于其根节点的值
                                         *      2) 右子树中所有节点的值,均大于其根节点的值
                                         *      3) 二叉搜索树的子树也是二叉搜索树
                                         */
#define tree_1_3        213             /** 2.1.3 平衡二叉树 AVL
                                         *      1) 平衡二叉树一定是一棵二叉查找树
                                         *      2) 任意节点的左右子树也是一棵平衡二叉树
                                         *      3) 从根节点开始,左右子树都高度差不能超过 1
                                         *      4)
                                         *      LL型调整 右旋
                                         *      RR型调整 左旋
                                         *      RL型调整 先右旋再左旋
                                         *      LR型调整 先左旋再右旋
                                         *      5) 红黑树
                                         *          a) 每个结点可以是黑色或是红色
                                         *          b) 根结点一定是黑色
                                         *          c) 红色结点的父结点和子结点不能为红色, 也就是说不能有两个连续的红色
                                         *          d) 所有的空结点都是黑色(空结点视为NIL,红黑树中是将空节点视为叶子结点)
                                         *          e) 每个结点到空节点(NIL)路径上出现的黑色结点的个数都相等
                                         *
                                         *          a) 如果整棵树为 NULL, 直接作为根结点, 变成黑色
                                         *          b) 如果父结点是黑色, 直接插入
                                         *          c) 如果父结点为红色, 且父结点的兄弟结点也是红色, 直接变色即可(注意得继续往上看有没有破坏之前的结构)
                                         *          d) 如果父结点为红色, 但父结点的兄弟结点为黑色, 需要先根据情况(LL、RR、LR、RL)进行旋转, 然后再变色
                                         */
#define tree_2          220         /** 2.2 B树 & B+树
                                     *      B
                                     *      1) 树中每个结点最多含有m个孩子(m >= 2)比如上面就是m为4的4阶B树, 最多有4个孩子
                                     *      2) 除根结点和叶子结点外, 其它每个结点至少有⌈m/2⌉个孩子, 同理键值数量至少有⌈m/2⌉-1个
                                     *      3) 若根结点不是叶子结点, 则至少有2个孩子
                                     *      4) 所有叶子结点都出现在同一层
                                     *      5) 一个结点的包含多种信息(P0, K1, P1, K2,..., Kn, Pn), 其中P为指向子树的指针, K为键值(关键字)
                                     *          a) Ki (i=1...n)为键值, 也就是每个结点保存的值, 且键值按顺序升序排序 K(i-1)< Ki
                                     *          b) Pi为指向子树的指针, 且指针Pi指向的子树中所有结点的键值均小于Ki, 但都大于K(i-1)
                                     *          c) 键值的个数n必须满足: ⌈m/2⌉-1 <= n <= m-1
                                     *
                                     *      6)
                                     *          a)若删除的是叶子结点的中元素
                                     *              i 正常情况下直接删除
                                     *              ii 如果删除后, 键值数小于最小值, 那么需要找兄弟借一个
                                     *              iii 要是没得借了, 直接跟兄弟结点、对应的分割值合并
                                     *          b) 若删除的是某个根结点中的元素
                                     *              i 一般情况会删掉一个分割值, 删掉后需要重新从左右子树中找一个新分割值的拿上来
                                     *              ii 要是拿上来之后左右子树中出现键值数小于最小值的情况, 那么就只能合并了
                                     *          c) 上述两个操作执行完后, 还要继续往上看上面的结点是否依然满足性质, 否则继续处理, 直到稳定
                                     *
                                     *       B+
                                     *       1) 有k个子树的中间结点包含有k个元素(B树中是k-1个元素), 每个元素不保存数据, 只用来索引, 所有数据(卫星数据, 就是具体需要保存的内容)都保存在叶子结点
                                     *       2) 所有的叶子结点中包含了全部元素的信息, 及指向含这些元素记录的指针, 且叶子结点按照从小到大的顺序连接
                                     *       3) 所有的根结点元素都同时存在于子结点中, 在子节点元素中是最大(或最小)元素
                                     */
#define tree_3          230         /** 2.3 哈夫曼树 */
#define tree_4          240         /** 2.4 堆和优先队列
                                     *      Heap: 完全二叉树
                                     *      diff: 堆, 子节点都比根节点小
                                     *            二叉查找树, 左节点小于根节点, 右节点大于根节点
                                     */

/**********************************************************************************
 * 3. 散列表                                                                       *
 **********************************************************************************/
#define hash_1          310         /** 3.1 哈希函数 & 哈希表 */
#define hash_1_1        311             /** 3.1.1 线性探测法
                                         *      1) 开放定址法
                                         *      2) 平方探测法
                                         *      3) 双散列法(两侧查找)
                                         *      ...
                                         */
#define hash_1_2        312             /** 3.1.2 链地址法 */

/**********************************************************************************
 * 4. 图                                                                          *
 **********************************************************************************/
#define graph_1         410         /** 4.1 邻接矩阵 */
#define graph_2         420         /** 4.2 邻接表 */
#define graph_3         430         /** 4.3 深度优先 */
#define graph_4         440         /** 4.4 广度优先 */
#define graph_5         450         /** 4.5 生成树 & 最小生成树
                                     *      1) Prim: 从任意节点开始, 选择最小的边延伸, 生成最小生成树
                                     *      2) Kruskal: 选择任意最小边 的 两个点 不断组成, 生成最小生成树
                                     */
#define graph_6         460         /** 4.6 单源最短路径 & 顶点最短路径
                                     *      1) Dijkstra: 统计到点到点的距离, 出现最短距离覆盖之, 得到第一个顶点到其它顶点的最短距离
                                     *      2) Floyd: 任意两个顶点的最短距离
                                     */
#define graph_7         470         /** 4.7 拓扑排序
                                     *      有向无环图(DAG), AOV, 将入度为0的加入队列, 出队形成顺序
                                     */
#define graph_8         480         /** 4.8 关键路径 */

/**********************************************************************************
 * 5. 排序                                                                         *
 **********************************************************************************/
#define sort_1          510         /** 5.1 冒泡
                                     *      两两对比, 交换位置
                                     *      1) 时间复杂度
                                     *          Best:  O(n), 有序
                                     *          Worst: O(n^2), 倒序
                                     *      2) 空间复杂度 O(1)
                                     *      3) 稳定
                                     */
#define sort_2          520         /** 5.2 插入
                                     *      数组前面部分的元素默认是以排好序的, 若元素不符合则将其插入前面部分合适位置
                                     *      1) 时间复杂度
                                     *          Best:  O(n), 有序
                                     *          Worst: O(n^2), 倒序
                                     *      2) 空间复杂度 O(1)
                                     *      3) 稳定
                                     */
#define sort_3          530         /** 5.3 选择
                                     *      每次遍历选择最小/大的元素放置数组前面
                                     *      1) 时间复杂度
                                     *          Best:  O(n^2)
                                     *          Worst: O(n^2)
                                     *      2) 空间复杂度 O(1)
                                     *      3) 不稳定
                                     */
#define sort_4          540         /** 5.4 快排
                                     *      a) 选择首位元素作为基准,
                                     *      b) 先从右往左, 比该元素小的元素交换位置
                                     *      c) 后从左往右遍历, 比基准元素大交换, 以此为基准, 重复b)
                                     *      d) 当左右交集, 以中心为基准元素(至此左边都比该元素小, 右边都比该元素大), 重复a) b) c) d)
                                     *
                                     *      1) 时间复杂度
                                     *          Best:  O(nlog(n))
                                     *          Worst: O(n^2)
                                     *      2) 空间复杂度 O(log(n))
                                     *      3) 不稳定
                                     */
#define sort_5          550         /** 5.5 希尔
                                     *      插入排序的改进
                                     *      a) 如以n/2为步长, 将数组分组, 组内插入排序
                                     *      b) 再规定步长为 步长/2, 重复 a) b) 直至步长为1
                                     *
                                     *      1) 时间复杂度
                                     *          Best:  O(n^1.3)
                                     *          Worst: O(n^2)
                                     *      2) 空间复杂度 O(1)
                                     *      3) 不稳定
                                     */
#define sort_6          560         /** 5.6 堆
                                     *
                                     *      1) 时间复杂度
                                     *          Best:  O(nlog(n))
                                     *          Worst: O(nlog(n))
                                     *      2) 空间复杂度 O(1)
                                     *      3) 不稳定
                                     */
#define sort_7          570         /** 5.7 归并
                                     *      递归分治, 合并以最小的填入
                                     *      1) 时间复杂度
                                     *          Best:  O(n + k)
                                     *          Worst: O(nlog(n))
                                     *      2) 空间复杂度 O(n), 需要额外的辅助空间
                                     *      3) 稳定
                                     */
#define sort_8          580         /** 5.8 计数
                                     *      定义长度为 N 的数组, 统计次数
                                     *      1) 时间复杂度
                                     *          Best:  O(n + k)
                                     *          Worst: O(n + k)
                                     *      2) 空间复杂度 O(k)
                                     *      3) 稳定
                                     */
#define sort_9          590         /** 5.9 桶
                                     *
                                     *      1) 时间复杂度
                                     *          Best:  O(n + k)
                                     *          Worst: O(n^2)
                                     *      2) 空间复杂度 O(n + k)
                                     *      3) 稳定
                                     */
#define sort_10         5100        /** 5.10 基数
                                     *      0~9的数组, 以个位、十位、...依次统计, 取出有序
                                     *      1) 时间复杂度
                                     *          Best:  O(n * k)
                                     *          Worst: O(n * k)
                                     *      2) 空间复杂度 O(n + k)
                                     *      3) 稳定
                                     */

/** 选择器 */
#define selector sort_7


#endif //DATA_STRUCT_MAIN_H

顺序表

SeqList.c

#include <stdio.h>
#include <stdbool.h>
#include "SeqList.h"


#if(selector == seqList_1)
/**
 * @fun:   seqList_build
 * @brief: 动态的申请空间创建新的顺序表
 * @param: list
 * @param: capacity
 * @ret:   None
 */
void seqList_build(List *list, int capacity)
{
    list->capacity = capacity;
    list->array = malloc(sizeof(E) * (list->capacity + 1)); // 多申请一个空间,可作为截止
    if (list->array == NULL) return;  // 未申请到空间放回
    list->size = 0;
}

/**
 * @fun:   seqList_print
 * @brief: 遍历
 * @param: list
 * @ret:   None
 */
void seqList_print(List *list)
{
    for (int i = 0; i < list->size; i++)
    {
        printf("%d ", list->array[i]);
    }
    printf("\r\n");
}

/**
 * @fun:   seqList_set
 * @brief: 设置列表数据
 * @param: list
 * @param: index
 * @param: param
 * @ret:   None
 */
void seqList_set(List *list, int index, E param)
{
    if (index < 0 || index >= list->capacity) return;
    list->array[index] = param;
}

/**
 * @fun:   seqList_push
 * @brief: 压入数据
 * @param: list
 * @param: param
 * @ret:   None
 */
void seqList_push(List *list, E param)
{
//    if (list->size >= list->capacity) return;
    if (list->size >= list->capacity)
        list->capacity++;
        E * newListArray = realloc(list->array, sizeof(E) * (list->capacity + 1));
        if (newListArray == NULL) return; // 扩容申请新内存失败
        list->array = newListArray;
    list->array[list->size++] = param;
}

/**
 * @fun:   seqList_get
 * @brief: 获取列表数据
 * @param: list
 * @param: index
 * @ret:   E list->array[index]
 */
E seqList_get(List *list, int index)
{
    if (index < 0 || index >= list->capacity) return NULL;
    return list->array[index];
}

/**
 * @fun:   seqList_get
 * @brief: 获取列表数据
 * @param: list
 * @param: param
 * @ret:   index of param when first found or not
 */
int seqList_find(List *list, E param)
{
    for (int i = 0; i < list->size; i++)
        if (list->array[i] == param) return i;

    return - 1;
}


/**
 * @fun:   seqList_remove
 * @brief: 移除列表数据
 * @param: list
 * @param: index
 * @ret:   None
 */
void seqList_remove(List *list, int index)
{
    if (index < 0 || index >= list->capacity) return;
    list->size--;
    do
    {
        list->array[index] = list->array[index+1];
    } while (index++ < list->size);
}

/**
 * @fun:   seqList_pop
 * @brief: 弹出数据
 * @param: list
 * @param: if direction is 1 pop first index's data (FIFO, Queue),
 *         else pop last index's data (FILO, Stack)
 * @ret:   None
 */
void seqList_pop(List *list, int direction)
{
    if (list->size <= 0) return;
    list->size--;
    if (direction == 1) // Queue
    {
        for (int i = 0; i < list->size; i++)
            list->array[i] = list->array[i+1];
    }
    // Stack
    list->array[list->size] = NULL;
}

/**
 * @fun:   seqList_destroy
 * @brief: 销毁列表
 * @param: list
 * @ret:   None
 */
void seqList_destroy(List *list)
{
    list->capacity = 0;
    list->size = 0;
    free(list->array);
}

/*****************************************/
#elif(selector == seqList_2)
/**
 * @fun:   linkList_create
 * @brief: 创建链表
 * @param: head
 * @ret:   None
 */
void linkList_create(ListNode head) {
    head->next = NULL;
}

/**
 * @fun:   linkList_iterate
 * @brief: 创建链表
 * @param: head
 * @ret:   None
 */
void linkList_iterate(ListNode head) {
    while (head->next) {
        head = head->next;  // 头结点不存放数据
        printf("%d ", head->elem);
    }
    printf("\r\n");
}

/**
 * @fun:   linkList_add
 * @brief: 插入链表元素
 * @param: head
 * @param: index
 * @param: elem
 * @ret:   None
 */
void linkList_add(ListNode head, int index, int elem) {
    if (index < 1) return;
    while (--index) {
        head = head->next;
        if (head == NULL) return; // 当结点为空, 说明超出索引
    }
    ListNode node = malloc(sizeof(struct ListNode_t));
//    struct ListNode_t * node = malloc(sizeof(struct ListNode_t));
    if (node == NULL) return;    // 未申请到空间
    node->elem = elem;
    // eg.
    //   node->next
    //     |
    // 1 2 3 4
    //   |
    //  head
    node->next = head->next;
    head->next = node;
}

/**
 * @fun:   linkList_delete
 * @brief: 删除链表元素
 * @param: head
 * @param: index
 * @ret:   None
 */
void linkList_delete(ListNode head, int index) {
    if (index < 1) return;
    while (--index) {
        head = head->next;
        if (head == NULL) return;
    }
    // eg. index = 5
    // 1 2 3 4
    //       |
    //      head
    if (head->next == NULL) return; // 删除的索引越界

    // eg. index = 4
    //       node
    //         |
    // 1 2 3 4 5(x)
    //       |
    //      head
    ListNode node = head->next;
    head->next = node->next; // head->next = head->next->next
    free(node);     // 释放该结点内存
}

/**
 * @fun:   linkList_retrieve
 * @brief: 检索链表
 * @param: head
 * @param: index
 * @ret:   E head->elem: the index of elem
 */
E linkList_retrieve(ListNode head, int index) {
    if (index < 1) return NULL;
    while (index--) {
        head = head->next;
        if (head == NULL) return NULL;  // 索引超出
    }
    return head->elem;
}

/**
 * @fun:   linkList_search
 * @brief: 查找链表元素
 * @param: head
 * @param: elem
 * @ret:   index
 */
int linkList_search(ListNode head, E elem) {
    int index = 0;
    while (head->next) {
        head = head->next;
        index += 1;
        if (head->elem == elem) return index;
        else if (head == NULL) return -1;
    }
//    do {
//        head = head->next;
//        index++;
//        if (head->elem == elem) return index;
//    } while (head);
//    return -1;
}

/**
 * @fun:   linkList_length
 * @brief: 查找链表元素
 * @param: head
 * @ret:   length
 */
int linkList_length(ListNode head) {
    int index = 0;
    while (head->next) {
        head = head->next;
        index++;
    }
    return index;
}

/*****************************************/
#elif(selector == seqList_2_1)
/**
 * @fun:   dLinkList_init
 * @brief: 创建双向链表
 * @param: head
 * @ret:   None
 */
void dLinkList_init(dNode head)
{
    head->next = head->prev = NULL;
}

/**
 * @fun:   dLinkList_show
 * @brief: 遍历链表
 * @param: head
 * @ret:   None
 */
void dLinkList_show(dNode head)
{
    while (head->next)
    {
        head = head->next;
        printf("%d ", head->elem);
    }
    printf("\r\n");
}

/**
 * @fun:   dLinkList_insert
 * @brief: 双向链表插入
 * @param: head
 * @param: index
 * @param: elem
 * @ret:   None
 */
void dLinkList_insert(dNode head, int index, E elem) {
    if (index < 1) return;
    while (--index) {
        head = head->next;
        if (head == NULL) return;
    }

    dNode node = malloc(sizeof(struct doubleListNode_t));
    if (node == NULL) return;
    node->elem = elem;

    if (head->next != NULL)
    {
        // 非最后一个节点插入
        node->next = head->next;
        head->next->prev = node;
    } else {
        //最后一个节点插入
        node->next = NULL;
    }

    head->next = node;
    node->prev = head;
}

/**
 * @fun:   dLinkList_destroy
 * @brief: 双向链表销毁
 * @param: head
 * @param: index
 * @ret:   None
 */
void dLinkList_destroy(dNode head, int index)
{
    if (index < 1) return;
    while (--index) {
        head = head->next;
        if (head == NULL) return;
    }
    if (head->next == NULL) return; // 删除索引越界

    dNode node = head->next;
    if (head->next->next != NULL) {
        head->next = node->next;
        node->next->prev = head;
    } else {
        // 删除最后一个节点
        head->next = NULL;
    }
    free(node);
}


/*****************************************/
#elif(selector == seqList_2_2)

/**
 * @fun:   cLinkList_born
 * @brief: 创建循环单链表
 * @param: head
 * @ret:   None
 */
void cLinkList_born(cNode head)
{
    head->next = NULL;
}

/**
 * @fun:   cLinkList_scan
 * @brief: 遍历链表
 * @param: head
 * @ret:   None
 */
void cLinkList_scan(cNode head)
{
    if (head->next) {
        cNode start = head;
        head = head->next;
        while (head != start) {
            printf("%d ", head->value);
            head = head->next;
        }
        printf("\r\n");
    }
}

/**
 * @fun:   cLinkList_join
 * @brief: 循环链表插入
 * @param: head
 * @param: index
 * @param: value
 * @ret:   None
 */
void cLinkList_join(cNode head, int index, E value)
{
    cNode start = head;
    if (index < 1) return;
    while (--index) {
        head = head->next;
        if (head == start) return;
    }

    cNode node = malloc(sizeof(struct cycleLinkList_t));
    node->value = value;
    if (head->next != NULL)
    {
//        printf("+%d ", node->value);
        node->next = head->next;
        head->next = node;
    } else {
//        printf("-%d ", node->value);
        // 首次创建, 且在末尾插入
        node->next = head;
        head->next = node;
    }
}

/**
 * @fun:   cLinkList_kick
 * @brief: 循环链表移除
 * @param: head
 * @param: index
 * @ret:   None
 */
void cLinkList_kick(cNode head, int index)
{
    if (index < 1) return;

    cNode start = head;
    while (--index)
    {
        head = head->next;
        if (head == start) return;
    }

    if (head->next == NULL) return;

    cNode node = head->next;
    head->next = node->next;
//    printf("next next %d \r\n", head->next->next->value);
    free(node);
}


/*****************************************/
#elif(selector == seqList_3)
/**
 * @fun:   StackInit
 * @brief: 栈初始化
 * @param: stack
 * @param: capacity
 * @ret:   None
 */
void StackInit(Stack *stack, int capacity)
{
    stack->arr = malloc(sizeof(E) * capacity);
    if (stack->arr == NULL) return;
    stack->capacity = capacity;
    stack->top = -1;
}

/**
 * @fun:   pushStack
 * @brief: 压栈
 * @param: stack
 * @param: val
 * @ret:   None
 */
void pushStack(Stack *stack, E val)
{
    if (stack->top + 1 >= stack->capacity) return;
    stack->arr[++stack->top] = val;
}

/**
 * @fun:   popStack
 * @brief: 出栈
 * @param: stack
 * @ret:   E val
 */
E popStack(Stack *stack)
{
    if (stack->top - 1 == -1) return NULL;
    E val = stack->arr[--stack->top];
    stack->arr[stack->top] = NULL;
    return val;
}

/** 共享栈 */
/**
 * @fun:   pushShareStack
 * @brief: 共享栈压栈
 * @param: shareStack
 * @param: val
 * @param: dir: if dir = 0, push leftStack, else if dir = 1, push rightStack
 * @ret:   None
 */
void pushShareStack(ShareStack shareStack, E val, int dir)
{
    if (shareStack->leftTop > shareStack->rightTop) return;
    if (dir == 0) {         // 从左压栈
        shareStack->arr[shareStack->leftTop++] = val;
    } else if (dir == 1) {  // 从右压栈
        shareStack->arr[shareStack->rightTop--] = val;
    }
}

/**
 * @fun:   popShareStack
 * @brief: 共享栈出栈
 * @param: shareStack
 * @param: dir: if dir = 0, pop leftStack, else if dir = 1, pop rightStack
 * @ret:   None
 */
E popShareStack(ShareStack shareStack, int dir)
{
    if (dir == 0 && shareStack->leftTop - 1 >= 0) {
        return shareStack->arr[--shareStack->leftTop];
    } else if (dir == 1 && shareStack->rightTop + 1 <= shareStack->capacity) {
        return shareStack->arr[++shareStack->rightTop];
    }
    return NULL;
}

/** 链式 */
/**
 * @fun:   StackNodeInit
 * @brief: 栈初始化
 * @param: stack
 * @ret:   None
 */
void StackNodeInit(StackNode stack)
{
    stack->next = NULL;
}

/**
 * @fun:   isEmpty
 * @brief: 判空
 * @param: stack
 * @ret:   true/false
 */
_Bool isEmpty(StackNode stack)
{
    if (stack->next != NULL) return true;
    return false;
}

/**
 * @fun:   pushStackNode
 * @brief: 压栈
 * @param: stack
 * @param: val
 * @ret:   None
 */
void pushStackNode(StackNode stack, E val)
{
    StackNode node = malloc(sizeof(StackNode));
    node->val = val;
    node->next = stack->next;
    stack->next = node;
}

/**
 * @fun:   popStackNode
 * @brief: 出栈
 * @param: stack
 * @ret:   E val
 */
E popStackNode(StackNode stack)
{
    StackNode node = stack->next;
    E val = node->val;
    stack->next = stack->next->next;
    free(node);
    return val;
}
/*****************************************/
#elif(selector == seqList_4)
/** 循环 */
/**
 * @fun:   rQueueInit
 * @brief: 循环队列初始化
 * @param: queue
 * @param: capacity
 * @ret:   None
 */
void rQueueInit(rQueue queue, int capacity)
{
    queue->arr = malloc(sizeof(E) * capacity);
    if (queue->arr == NULL) return;

    queue->capacity = capacity;
    queue->front = queue->rear = 0;
}

/**
 * @fun:   rQueueIter
 * @brief: 循环队列遍历
 * @param: queue
 * @ret:   None
 */
void rQueueIter(rQueue queue)
{
    int i = queue->front;
    while (i != queue->rear)
    {
        i = (i + 1) % queue->capacity;
        printf("%d ", queue->arr[i]);
    }
    printf("\r\n");
}

/**
 * @fun:   isEmpty
 * @brief: 判满
 * @param: queue
 * @ret:   true/false
 */
_Bool isFull(rQueue queue)
{
    if ((queue->rear + 1) % queue->capacity == queue->front) return true;
    return false;
}

/**
 * @fun:   isEmpty
 * @brief: 判空
 * @param: queue
 * @ret:   true/false
 */
_Bool isEmpty(rQueue queue)
{
    if ((queue->front + 1) % queue->capacity == queue->rear) return true;
    return false;
}

/**
 * @fun:   inRQueue
 * @brief: 入队
 * @param: queue
 * @param: val
 * @ret:   None
 */
void inRQueue(rQueue queue, int val)
{
    queue->rear = (queue->rear + 1) % queue->capacity;
    queue->arr[queue->rear] = val;
}

/**
 * @fun:   outRQueue
 * @brief: 出队
 * @param: queue
 * @ret:   None
 */
E outRQueue(rQueue queue)
{
    queue->front = (queue->front + 1) % queue->capacity;
    E val = queue->arr[queue->front];
    queue->arr[queue->front] = NULL;
    return val;
}


/** 链式 */
void QueueLinkNodeInit(QueueLink queue)
{
    QueueNode node = malloc(sizeof(QueueNode));
    if (node == NULL) return;
    node->next = NULL;
    queue->front = queue->rear = node;
}

void QueueLinkNodeItr(QueueLink queue)
{
    QueueNode node = queue->front->next;
    while (1)
    {
        printf("%d ", node->val);
        if (node == queue->rear) break;
        node = node->next;
    }
    printf("\r\n");
}

void inQueueLinkNode(QueueLink queue, E val)
{
    QueueNode node = malloc(sizeof(QueueNode));
    if (node == NULL) return;
    node->next = NULL;
    node->val = val;
    // front
    // |
    //     node
    // |
    // rear
    queue->rear->next = node;
    // front
    // |
    //     node
    //      |
    //     rear
    queue->rear = node;
}

E outQueueLinkNode(QueueLink queue)
{
    QueueNode node = queue->front->next;
    E val = node->val;
    queue->front->next = node->next;
    if (node == queue->rear) queue->rear = queue->front; // 只有一个元素(队尾出队)
    free(node);
    return val;
}
/*****************************************/

#endif

SeqList.h

#ifndef DATA_STRUCT_SEQLIST_H
#define DATA_STRUCT_SEQLIST_H

#include <stdlib.h>
#include "main.h"

typedef int E;

#if(selector == seqList_1)
/** 顺序 */
typedef struct List_t {
    E *array;
    int capacity;
    int size;
}List;

void seqList_build(List *list, int capacity);
void seqList_print(List *list);
void seqList_set(List *list, int index, E param);
void seqList_push(List *list, E param);
E    seqList_get(List *List, int index);
int  seqList_find(List *list, E param);
void seqList_remove(List *list, int index);
void seqList_pop(List *list, int direction);
void seqList_destroy(List *list);

/*****************************************/
#elif(selector == seqList_2)
/** 链式 (定义为指针结构体) */
typedef struct ListNode_t {
    E elem;
    struct ListNode *next;
}* ListNode;


void linkList_create(ListNode head);
void linkList_add(ListNode head, int index, E elem);
void linkList_delete(ListNode head, int index);
void linkList_iterate(ListNode head);
E linkList_retrieve(ListNode head, int index);
int linkList_search(ListNode head, E elem);
int linkList_length(ListNode head);

/*****************************************/
#elif(selector == seqList_2_1)
/** 双向链表 */
typedef struct doubleListNode_t {
    E elem;
    struct doubleListNode_t *next;
    struct doubleListNode_t *prev;
}*dNode;

void dLinkList_init(dNode head);
void dLinkList_show(dNode head);
void dLinkList_insert(dNode head, int index, E elem);
void dLinkList_destroy(dNode head, int index);

/*****************************************/
#elif(selector == seqList_2_2)
/** 循环列表 */
typedef struct cycleLinkList_t {
  struct cycleLinkList_t *next;
//  struct cycleLinkList_t *prev;
  E value;
}*cNode;

void cLinkList_born(cNode head);
void cLinkList_scan(cNode head);
void cLinkList_join(cNode head, int index, E value);
void cLinkList_kick(cNode head, int index);
/*****************************************/
#elif(selector == seqList_3)
// 顺序存储
typedef struct Stack_t {
    E  *arr;
    int capacity;
    int top;
}Stack;

void StackInit(Stack *stack, int capacity);
void pushStack(Stack *stack, E val);
E    popStack(Stack *stack);
// 顺序存储 双栈共享栈
typedef struct ShareStack_t {
    E * arr;
    int capacity;
    int leftTop;
    int rightTop;
}*ShareStack;
void pushShareStack(ShareStack shareStack, E val, int dir);
E popShareStack(ShareStack shareStack, int dir);
// 链式存储(以头结点为栈底)
typedef struct StackNode_t {
    E val;
    struct StackNode_t *next;
}*StackNode;

void StackNodeInit(StackNode stack);
_Bool isEmpty(StackNode stack);
void pushStackNode(StackNode stack, E val);
E popStackNode(StackNode stack);

/*****************************************/
#elif(selector == seqList_4)
/** 顺序 */
typedef struct Queue_t {
    E *arr;
    int capacity;
}Queue;

/** 环形队列 */
typedef struct RingQueue_t
{
    E * arr;
    int capacity;
    int front, rear;
}*rQueue;

void rQueueInit(rQueue queue, int capacity);
_Bool isFull(rQueue queue); // 牺牲一个空间用于判断rear==front
_Bool isEmpty(rQueue queue); // 牺牲一个空间用于判断rear==front
void rQueueIter(rQueue queue);
void inRQueue(rQueue queue, int val);
E outRQueue(rQueue queue);

/** 链式(需要头尾双指针) */
typedef struct QueueNode_t
{
    E val;
    struct QueueNode_t *next;
}*QueueNode;

typedef struct QueueLink {
    QueueNode front, rear;
}*QueueLink;
void QueueLinkNodeInit(QueueLink queue);
void QueueLinkNodeItr(QueueLink queue);
void inQueueLinkNode(QueueLink queue, E val);
E outQueueLinkNode(QueueLink queue);
#endif

#endif //DATA_STRUCT_SEQLIST_H

队列

_Queue.c

#include "_Queue.h"

#if (selector < hash_1)
void _initQueue(_Queue queue)
{
    _QueueNode node = malloc(sizeof(_QueueNode));
    if(node == NULL) return;
    queue->front = queue->rear = node;
    node->next = NULL;
}

void _inQueue(_Queue queue, T elem)
{
    _QueueNode node = malloc(sizeof(_QueueNode));
    if(node == NULL) return;
    node->elem = elem;
    queue->rear->next = node;
    queue->rear = node;
//    printf("#in %c #\n", node->elem->elem);
}

T _outQueue(_Queue queue)
{
    _QueueNode node = queue->front->next;
    T elem = node->elem;
//    printf("#out %c #\n", elem->elem);
    queue->front->next = node->next;
    if(queue->rear == node) queue->rear = queue->front;
    free(node);
    return elem;
}

#if (selector == tree_3)
void _priorityJoinQueue(_Queue queue, T elem)
{
    _QueueNode node = malloc(sizeof(_QueueNode));
    if (node == NULL) return;
    node->elem = elem;
    node->next = NULL;

    _QueueNode pre = queue->front;
    // 移至合适权重的位置, 插入队列
    while (pre->next && pre->next->elem->weights <= elem->weights) // 权重小在前
    {
        pre = pre->next;
    }
    if (pre == queue->rear)          // 如果是最后, 直接插入
    {
        queue->rear->next = node;
        queue->rear = node;
    } else {                         // 中间插队
        node->next = pre->next;
        pre->next = node;
    }
}
#endif
#elif (selector == graph_4)
_Bool _initQueue(_LinkedQueue queue){
    _QNode node = malloc(sizeof(struct _QueueNode));
    if(node == NULL) return 0;
    queue->front = queue->rear = node;
    return 1;
}

_Bool _offerQueue(_LinkedQueue queue, T element){
    _QNode node = malloc(sizeof(struct _QueueNode));
    if(node == NULL) return 0;
    node->element = element;
    queue->rear->next = node;
    queue->rear = node;
    return 1;
}

_Bool _isEmpty(_LinkedQueue queue){
    return queue->front == queue->rear;
}

T _pollQueue(_LinkedQueue queue){
    T e = queue->front->next->element;
    _QNode node = queue->front->next;
    queue->front->next = queue->front->next->next;
    if(queue->rear == node) queue->rear = queue->front;
    free(node);
    return e;
}

#endif

_Queue.h

#ifndef DATA_STRUCT__QUEUE_H
#define DATA_STRUCT__QUEUE_H

#include <malloc.h>
#include "main.h"

#ifdef selector
#if (selector < tree_1)
//#include "SeqList.h"
#elif (selector < hash_1)
#include "Tree.h"

//typedef struct _Queue_t {
//    T elem;
//    struct _Queue_t *next, *front, *rear;;
//}*_Queue;

typedef struct _QueueNode_t {
    T elem;
    struct _QueueNode_t * next;
}*_QueueNode;

typedef struct _Queue_t {
    _QueueNode front, rear;
}*_Queue;

void _initQueue(_Queue queue);
void _inQueue(_Queue queue, T elem);
T _outQueue(_Queue queue);
void _priorityJoinQueue(_Queue queue, T elem);

#elif (selector < graph_1)
#include "Hash.h"
#elif (selector < sort_1)
#include "Graph.h"
typedef int T;   //这里将顶点下标作为元素

typedef struct _QueueNode {
    T element;
    struct _QueueNode * next;
} * _QNode;

typedef struct _Queue {
    _QNode front, rear;
} * _LinkedQueue;

_Bool _initQueue(_LinkedQueue queue);
_Bool _offerQueue(_LinkedQueue queue, T element);
_Bool _isEmpty(_LinkedQueue queue);
T _pollQueue(_LinkedQueue queue);

#else
//#include "Sort.h"
#endif
#endif

#endif //DATA_STRUCT__QUEUE_H

_Stack.c

#include <malloc.h>
#include "_Stack.h"

#if (selector < hash_1)
void _initStack(_Stack stack)
{
    stack->next = NULL;
}

void _pushStack(_Stack stack, T elem)
{
    _Stack node = malloc(sizeof(_Stack));
    if(node == NULL) return;
    node->next = stack->next;
    node->elem = elem;
    stack->next = node;
}

T _popStack(_Stack stack)
{
    _Stack node = stack->next;
    if (node == NULL) return NULL;
    T elem = node->elem;
    stack->next = stack->next->next;
    free(node);
    return elem;
}

// 获取栈顶元素, 但不出栈
T _peekStack(_Stack stack)
{
    return stack->next->elem;
}
#endif

_Stack.h

#ifndef DATA_STRUCT__STACK_H
#define DATA_STRUCT__STACK_H
#include "main.h"

#ifdef selector
#if (selector < tree_1)
//#include "SeqList.h"
#elif (selector < hash_1)

#include "Tree.h"

typedef struct _StackNode_t {
    T elem;
    struct _StackNode_t *next;
}*_Stack;

void _initStack(_Stack stack);
void _pushStack(_Stack stack, T elem);
T _popStack(_Stack stack);
T _peekStack(_Stack stack);

#elif (selector < graph_1)
#include "Hash.h"
#elif (selector < sort_1)
#include "Graph.h"
#else
//#include "Sort.h"
#endif
#endif

#endif //DATA_STRUCT__STACK_H

Tree.c

#include "Tree.h"
#include <math.h>
#include <malloc.h>
#include <string.h>
#include "_Stack.h"
#include "_Queue.h"

#if (selector == tree_1)
/** 二叉树  */
/**
 * @fun:   countBinaryTreeNum
 * @data:  2022/9/17
 * @brief: 根据节点计算生成的二叉树的个数
 * @param: nodesNum: 节点个数
 * @ret:   dp[nodesNum]
 */
int countBinaryTreeNum(int nodesNum)
{
    // 动态规划
    int dp[nodesNum + 1];
    dp[0] = dp[1] = 1;
    for (int i = 2; i <= nodesNum; i++)
    {
        dp[i] = 0;
        for (int j = 0; j < i; j++)
        {
            dp[i] = dp[i - j - 1] + dp[j];
        }
    }
    return dp[nodesNum];
}

/**
 * @fun:   completeBinaryTreeLeafNodesNum
 * @data:  2022/9/17
 * @brief: 估计节点计算完全二叉树叶子节点个数
 * @param: nodesNum
 * @ret:
 */
int completeBinaryTreeLeafNodesNum(int nodesNum)
{
    int depth = (ceil)((int)log(nodesNum)) + 1;
    // 从第一层到倒数第二层的节点个数
    int first_to_last2nd_depth_nodesNum = pow(2, (depth-1)) - 1;
    // 最后一层的(叶子)节点个数
    int last_depth_nodesNum = nodesNum - first_to_last2nd_depth_nodesNum;
    // 倒数第二层的节点个数
    int last2nd_depth_nodes_Num = pow(2, depth-2);
    // 倒数第二层的节点个数 去除 倒数第二层度为1和2的节点(最后一层叶子节点数+1)/2确保度为1的节点偶数 (剩下为该层的叶子节点) 与 最后一层的叶子节点 之和
    return last2nd_depth_nodes_Num - (last_depth_nodesNum + 1) / 2 + last_depth_nodesNum;

}

/**
 * @fun:   fullBinaryTreeNodesNum
 * @data:  2022/9/17
 * @brief: 根据深度计算满二叉树的节点个数
 * @param: depth
 * @ret:   m^(k-1),     (m = 2)
 */
int fullBinaryTreeNodesNum(int depth)
{
    return pow(2, depth - 1);
}

/**
 * @fun:   BinaryTreeDepth
 * @data:  2022/9/17
 * @brief: 根据节点个数求二叉树的深度范围
 * @param: nodesNum
 * @ret:   *res       [完全二叉树, 单枝树]
 */
int* BinaryTreeDepth(int nodesNum)
{
    int *res;
    res[0] = log(nodesNum - 1);
    res[1] = nodesNum;
    return res;
}


/**
 * @fun:   BinaryTreeBuild
 * @data:  2022/9/17
 * @brief: 二叉树构建
 * @param: leftChild
 * @param: rightChild
 * @param: E elem
 * @ret:   None
 */
BinaryTree BinaryTreeBuild(BinaryTree leftChild, BinaryTree rightChild, E elem)
{
    BinaryTree tree = malloc(sizeof(BinaryTree));
    tree->elem = elem;
    tree->leftChild = leftChild;
    tree->rightChild = rightChild;
    return tree;
}

/**
 * @fun:   BinaryTreePreOrderTraversal
 * @data:  2022/9/18
 * @brief: 前序遍历 root-left-right
 * @param: tree
 * @ret:   None
 */
void BinaryTreePreOrderTraversal(BinaryTree tree)
{
    // 递归
//    if (tree == NULL) return;
    printf("%c ", tree->elem);
    if (tree->leftChild)  BinaryTreePreOrderTraversal(tree->leftChild);
    if (tree->rightChild) BinaryTreePreOrderTraversal(tree->rightChild);
}
/**
 * @fun:   BinaryTreePreOrder
 * @data:  2022/9/18
 * @brief: 前序遍历 root-left-right
 * @param: tree
 * @ret:   None
 */
void BinaryTreePreOrder(BinaryTree tree)
{
    _Stack stack;
    _initStack(&stack);
    // 判断节点空 且 栈空
    while (tree && stack->next)
    {
        while (tree)
        {
            // 记录存储根左枝
            printf("%c ", tree->elem);
            _pushStack(&stack, tree);
            tree = tree->leftChild;
        }
        // 从尾依次寻右枝
        tree = _popStack(&stack);
        tree = tree->rightChild;
    }
}

/**
 * @fun:   BinaryTreeInorderTraversal
 * @data:  2022/9/18
 * @brief: 中序遍历 left-root-right
 * @param: tree
 * @ret:   None
 */
void BinaryTreeInorderTraversal(BinaryTree tree)
{
    if (tree->leftChild)  BinaryTreeInorderTraversal(tree->leftChild);
    printf("%c ", tree->elem);
    if (tree->rightChild)  BinaryTreeInorderTraversal(tree->rightChild);
}

/**
 * @fun:   BinaryTreeInorder
 * @data:  2022/9/18
 * @brief: 中序遍历 left-root-right
 * @param: tree
 * @ret:   None
 */
void BinaryTreeInorder(BinaryTree tree)
{
    _Stack stack;
    _initStack(&stack);
    // 判断节点空 栈空
    while (tree || stack->next)
    {
        while (tree)
        {
            // 记录存储左枝
            _pushStack(&stack, tree);
            tree = tree->leftChild;
        }
        // 从尾依次寻根右枝
        tree = _popStack(&stack);
        printf("%c ", tree->elem);
        tree = tree->rightChild;
    }
}

/**
 * @fun:   BinaryTreePostOrderTraversal
 * @data:  2022/9/18
 * @brief: 后序遍历 left-right-root
 * @param: tree
 * @ret:   None
 */
void BinaryTreePostOrderTraversal(BinaryTree tree)
{
    if (tree->leftChild)  BinaryTreeInorderTraversal(tree->leftChild);
    if (tree->rightChild)  BinaryTreeInorderTraversal(tree->rightChild);
    printf("%c ", tree->elem);
}

/**
 * @fun:   BinaryTreePostOrder
 * @data:  2022/9/18
 * @brief: 后序遍历 left-right-root
 * @param: tree
 * @ret:   None
 */
void BinaryTreePostOrder(BinaryTree tree)
{
    _Stack stack;
    _initStack(&stack);
    // 判断节点空 栈空
    while (tree || stack->next)
    {
        // left to lastLeft
        while (tree)
        {
            // 记录存储左枝 并标记
            _pushStack(&stack, tree);
            tree->flag = 0;
            tree = tree->leftChild;
        }
        // lastLeft->parent
        tree = _peekStack(tree);
        // lastLeft->parent->right
        if (tree->flag == 0)
        {
            // 标记右枝
            tree->flag = 1;
            tree = tree->rightChild;
        }
        else
        {
            // left root right
           printf("%c ", tree->elem);
           _popStack(&stack);
           tree = NULL;
        }
        // 从尾依次寻根右枝
    }
}

///**
// * @fun:   BinaryTreeLevelOrderTraversal
// * @data:  2022/9/18
// * @brief: 层序遍历
// * @param: tree
// * @ret:   None
// */
//void BinaryTreeLevelOrderTraversal(BinaryTree tree)
//{
//
//}

/**
 * @fun:   BinaryTreeLevelOrder
 * @data:  2022/9/18
 * @brief: 层序遍历
 * @param: tree
 * @ret:   None
 */
void BinaryTreeLevelOrder(BinaryTree tree)
{
//    _Queue queue;
    struct _Queue_t q;
    _initQueue(&q);
//    _inQueue(&queue, tree);
//    printf("%c ", _outQueue(&queue)->elem);
//    _inQueue(&queue, tree->leftChild);
//    _inQueue(&queue, tree->rightChild);
//    printf("%c ", _outQueue(&queue)->elem);
//    _inQueue(&queue, tree->leftChild->leftChild);
//    printf("%c ", _outQueue(&queue)->elem);
//    printf("%c ", _outQueue(&queue)->elem);

    _inQueue(&q, tree);
    while(q.front != q.rear)
    {
        BinaryTree node = _outQueue(&q);
        printf("%c ", node->elem);
        // 存在左右枝入队
        if(node->leftChild)  { _inQueue(&q, node->leftChild);  }
        if(node->rightChild) { _inQueue(&q, node->rightChild); }
    }
}
#elif (selector == tree_1_1)
/**
 * @fun:   buildNode
 * @data:  2022/9/20
 * @brief: 创建节点
 * @param: elem
 * @ret:   node
 */
TreeNode buildNode(E elem)
{
    TreeNode node = malloc(sizeof(TreeNode));
    node->leftChild = node->rightChild = NULL;
    node->leftTag = node->rightTag = 0;
    node->elem = elem;
    return node;
}

TreeNode pre = NULL;
TreeNode preInit()
{
    return NULL;
}

/**
 * @fun:   preOrderThreaded
 * @data:  2022/9/20
 * @brief: 前序遍历线索化
 * @param: root
 * @ret:   None
 */
void preOrderThreaded(TreeNode root)
{
    if(root == NULL) return;

    //首先判断当前节点左边是否为NULL, 如果是, 那么指向上一个节点
    if(root->leftChild == NULL) {
        root->leftChild = pre;
        root->leftTag = 1;
    }

    //然后是判断上一个节点的右边是否为NULL, 如果是那么进行线索化, 指向当前节点
    if(pre && pre->rightChild == NULL) {
        pre->rightChild = root;
        pre->rightTag = 1;
    }

    pre = root;

    if(root->leftTag == 0) preOrderThreaded(root->leftChild);
    if(root->rightTag == 0) preOrderThreaded(root->rightChild);
}

/**
 * @fun:   preOrder
 * @data:  2022/9/20
 * @brief: 线索化后的前序遍历
 * @param: root
 * @ret:   None
 */
void preOrder(TreeNode root)
{
    while (root) {   //到头为止
        printf("%c", root->elem);   //因为是前序遍历, 所以直接按顺序打印就行了
        if(root->leftTag == 0)
            root = root->leftChild;   //如果是左孩子, 那么就走左边
        else
            root = root->rightChild;   //如果左边指向的不是孩子, 而是线索, 那么就直接走右边, 因为右边无论是线索还是孩子, 都要往这边走了
    }
}

/**
 * @fun:   inOrderThreaded
 * @data:  2022/9/20
 * @brief: 中序遍历线索化
 * @param: root
 * @ret:   None
 */
void inOrderThreaded(TreeNode root)
{
    if(root == NULL) return;

    if(root->leftTag == 0) preOrderThreaded(root->leftChild);

    //首先判断当前节点左边是否为NULL, 如果是, 那么指向上一个节点
    if(root->leftChild == NULL) {
        root->leftChild = pre;
        root->leftTag = 1;
    }

    //然后是判断上一个节点的右边是否为NULL, 如果是那么进行线索化, 指向当前节点
    if(pre && pre->rightChild == NULL) {
        pre->rightChild = root;
        pre->rightTag = 1;
    }

    pre = root;

    if(root->rightTag == 0) preOrderThreaded(root->rightChild);
}

/**
 * @fun:   inOrder
 * @data:  2022/9/20
 * @brief: 线索化中序遍历
 * @param: root
 * @ret:   None
 */
void inOrder(TreeNode root)
{
    while (root) {   //因为中序遍历需要先完成左边, 所以说要先走到最左边才行
        while (root && root->leftTag == 0)    //如果左边一直都不是线索, 那么就一直往左找, 直到找到一个左边是线索的为止, 表示到头了
            root = root->leftChild;

        printf("%c", root->elem);   //到最左边了再打印, 中序开始

        while (root && root->rightTag == 1) {   //打印完就该右边了, 右边如果是线索化之后的结果, 表示是下一个节点, 那么就一路向前, 直到不是为止
            root = root->rightChild;
            printf("%c", root->elem);   //注意按着线索往下就是中序的结果, 所以说沿途需要打印
        }
        root = root->rightChild;  //最后继续从右节点开始, 重复上述操作
    }
}

/**
 * @fun:   postOrderThreaded
 * @data:  2022/9/20
 * @brief: 后序遍历线索化
 * @param: root
 * @ret:   None
 */
void postOrderThreaded(TreeNode root)
{
    if(root == NULL) return;
    if(root->leftTag == 0) {
        postOrderThreaded(root->leftChild);
        if(root->leftChild) root->leftChild->parent = root;  //左边完事之后, 如果不为空, 那么就设定父子关系
    }
    if(root->rightTag == 0) {
        postOrderThreaded(root->rightChild);
        if(root->rightChild) root->rightChild->parent = root;   //右边完事之后, 如果不为空, 那么就设定父子关系
    }
    //------  线索化 -------
    if(root->leftChild == NULL) {
        root->leftChild = pre;
        root->leftTag = 1;
    }
    if(pre && pre->rightChild == NULL) {
        pre->rightChild = root;
        pre->rightTag = 1;
    }
    pre = root;
    //--------------------
}

/**
 * @fun:   postOrder
 * @data:  2022/9/20
 * @brief: 线索化后的后序遍历
 * @param: root
 * @ret:   None
 */
void postOrder(TreeNode root)
{
    TreeNode last = NULL, node = root;  //这里需要两个暂存指针, 一个记录上一次遍历的节点, 还有一个从root开始
    while (node) {
        while (node->leftChild != last && node->leftTag == 0)    //依然是从整棵树最左边节点开始, 和前面一样, 只不过这里加入了防无限循环机制, 看到下面就知道了
            node = node->leftChild;
        while (node && node->rightTag == 1) {   //左边完了还有右边, 如果右边是线索, 那么直接一路向前, 也是跟前面一样的
            printf("%c", node->elem);   //沿途打印
            last = node;
            node = node->rightChild;
        }
        if (node == root && node->rightChild == last) {
            //上面的操作完成之后, 那么当前节点左右就结束了, 此时就要去寻找其兄弟节点了, 我们可以
            //直接通过parent拿到兄弟节点, 但是如果当前节点是根节点, 需要特殊处理, 因为根节点没有父节点了
            printf("%c", node->elem);
            return;   //根节点一定是最后一个, 所以说直接返回就完事
        }
        while (node && node->rightChild == last) {    //如果当前节点的右孩子就是上一个遍历的节点, 那么一直向前就行
            printf("%c", node->elem);   //直接打印当前节点
            last = node;
            node = node->parent;
        }
        //到这里只有一种情况了, 是从左子树上来的, 那么当前节点的右边要么是线索要么是右子树, 所以直接向右就完事
        if(node && node->rightTag == 0) {  //如果不是线索, 那就先走右边, 如果是, 等到下一轮再说
            node = node->rightChild;
        }
    }
}
#elif (selector == tree_1_2)
/**
 * @fun:   buildNode
 * @data:  2022/9/24
 * @brief: 构建节点
 * @param: elem
 * @ret:   node
 */
Node buildNode(E elem) {
    Node node = malloc(sizeof(Tree));
    node->left = node->right = NULL;
    node->elem = elem;
    return node;
}

/**
 * @fun:   insertNode
 * @data:  2022/9/24
 * @brief: 插入节点构建查找二叉树, 值大放于右子树, 值小放于左子树, 不能值相同
 * @param: root, elem
 * @ret:   root
 */
Node insertNode(Node root, E elem)
{
    if(root)
    {
        if (root->elem > elem)
            root->left = insertNode(root->left, elem);
        else if (root->elem < elem)
            root->right = insertNode(root->right, elem);
    } else {
        root = buildNode(elem);
    }
    return root;
}

/**
 * @fun:   searchNode
 * @data:  2022/9/24
 * @brief: 二叉查找树
 * @param: root, target
 * @ret:   root/NULL
 */
Node searchNode(Node root, E target)
{
    while (root)
    {
        if (root->elem > target)
            root = root->left;
        else if (root->elem < target)
            root = root->right;
        else
            return root;
        return NULL;
    }
}

/**
 * @fun:   maxNode
 * @data:  2022/9/24
 * @brief: 寻找最大节点
 * @param: root
 * @ret:   root
 */
Node maxNode(Node root)
{
    while (root && root->right)
        root = root->right;
    return root
}

/**
 * @fun:   minNode
 * @data:  2022/9/24
 * @brief: 寻找最小节点
 * @param: root
 * @ret:   root
 */
Node minNode(Node root)
{
    while (root && root->left)
        root = root->left;
    return root;
}

/**
 * @fun:   removeNode
 * @data:  2022/9/24
 * @brief: 移除节点
 * @param: root, target
 * @ret:   root
 */
Node removeNode(Node root, E target)
{
    if (root == NULL) return NULL;

    if (root->elem > target) { root = removeNode(root->left, target); }
    if (root->elem < target) { root = removeNode(root->right, target); }
    else { // root->elem == target
        if (root->left && root->right)
        {
            // 将找到待删除的节点 替换 成 左子树最大节点, 再在该子树下 依次 删除这 用于替换的最大节点
            Node max = maxNode(root->left);
            root->elem = max->elem;
            root->left = removeNode(root->left, root->elem);
        } else { // 倒数第二层只有单叶 或 叶子节点
            Node tmp = root;
            if (root->right) { root = root->right; }
            else { root = root->left; }
            free(tmp);
        }
    }
    return root;
}
#elif (selector == tree_1_3)
/** LL型调整 右旋 */
/** RR型调整 左旋 */
/** LR型调整 先左旋再右旋 */
/** RL型调整 先右旋再左旋 */

/**
 * @fun:   makeNode
 * @data:  2022/9/24
 * @brief: 制作节点
 * @param: 
 * @ret:   
 */
Node makeNode(I element){
    Node node = malloc(sizeof(struct TreeNode));
    node->left = node->right = NULL;
    node->element = element;
    node->height = 1;               //初始化高度为1
    return node;
}

I max(I e1, I e2)
{
    return e1 > e2 ? e1 : e2;
}
/**
 * @fun:   getHeight
 * @data:  2022/9/24
 * @brief: 获取高度
 * @param: 
 * @ret:   
 */
int getHeight(Node root) {
    if(root == NULL) return 0;
    return root->height;
}

/**
 * @fun:   leftRotation
 * @data:  2022/9/24
 * @brief: 左旋操作, 实际上就是把左边节点拿上来
 * @param: 
 * @ret:   
 */
Node leftRotation(Node root) {
    Node newRoot = root->right;     // 先得到左边节点
    root->right = newRoot->left;    // 将左边节点的左子树丢到原本根节点的右边去
    newRoot->left = root;           // 现在新的根节点左边就是原本的根节点了

    root->height = max(getHeight(root->right), getHeight(root->left)) + 1;
    newRoot->height = max(getHeight(newRoot->right), getHeight(newRoot->left)) + 1;
    return newRoot;
}

/**
 * @fun:   rightRotation
 * @data:  2022/9/24
 * @brief: 右旋操作, 实际上就是把右边节点拿上来
 * @param: 
 * @ret:   
 */
Node rightRotation(Node root) {
    Node newRoot = root->left;
    root->left = newRoot->right;
    newRoot->right = root;

    root->height = max(getHeight(root->right), getHeight(root->left)) + 1;
    newRoot->height = max(getHeight(newRoot->right), getHeight(newRoot->left)) + 1;
    return newRoot;
}

/**
 * @fun:   leftRightRotation
 * @data:  2022/9/24
 * @brief: 先左后右
 * @param: 
 * @ret:   
 */
Node leftRightRotation(Node root) {
    root->left = leftRotation(root->left);
    return rightRotation(root);
}

/**
 * @fun:   rightLeftRightRotation
 * @data:  2022/9/24
 * @brief: 先右后左
 * @param: 
 * @ret:   
 */
Node rightLeftRightRotation(Node root) {
    root->right = rightRotation(root->right);
    return leftRotation(root);
}

/**
 * @fun:   insert
 * @data:  2022/9/24
 * @brief: 插入节点
 * @param: 
 * @ret:   
 */
Node insert(Node root, I element) {
    if(root == NULL) {    //如果节点为NULL, 说明找到了插入位置, 直接创建新的就完事
        root = makeNode(element);
    }else if(root->element > element) {   //和二叉搜索树一样, 判断大小, 该走哪边走哪边, 直到找到对应插入位置
        root->left = insert(root->left, element);
        if(getHeight(root->left) - getHeight(root->right) > 1) {   //插入完成之后, 需要计算平衡因子, 看看是否失衡
            if(root->left->element > element) //接着需要判断一下是插入了左子树的左边还是右边, 如果是左边那边说明是LL, 如果是右边那说明是LR
                root = rightRotation(root);   //LL型得到左旋之后的结果, 得到新的根节点
            else
                root = leftRightRotation(root);    //LR型得到先左旋再右旋之后的结果, 得到新的根节点
        }
    }else if(root->element < element){
        root->right = insert(root->right, element);
        if(getHeight(root->left) - getHeight(root->right) < -1){
            if(root->right->element < element)
                root = leftRotation(root);
            else
                root = rightLeftRightRotation(root);
        }
    }
    // 前面的操作完成之后记得更新一下树高度
    root->height = max(getHeight(root->left), getHeight(root->right)) + 1;
    return root;  //最后返回root到上一级
}
#elif (selector == tree_2)

#elif (selector == tree_3)
/**
 * @fun:   createNode
 * @data:  2022/10/5
 * @brief: 
 * @param: 
 * @ret:   
 */
HuffmanTree createNode(E elem, int weights)
{
    HuffmanTree node = malloc(sizeof(HuffmanTree));
    node->elem = elem;
    node->left = node->right = NULL;
    node->weights = weights;
    return node;
}

/**
 * @fun:   buildHuffmanTree
 * @data:  2022/10/5
 * @brief: 构建哈夫曼树
 * @param: 
 * @ret:   
 */
//void buildHuffmanTree(HuffmanTree root)
HuffmanTree buildHuffmanTree(char alpha[], int weights[], int size)
{
    struct _Queue_t queue;
    _initQueue(&queue);
    for (int i = 0; i < size; i++)
    {
        _priorityJoinQueue(&queue, createNode(alpha[i], weights[i]));
    }
//    _priorityJoinQueue(&queue, createNode('B', 11));
//    _priorityJoinQueue(&queue, createNode('C', 3));
//    _priorityJoinQueue(&queue, createNode('D', 6));
//    _priorityJoinQueue(&queue, createNode('E', 2));

    while (queue.front->next != queue.rear)
    {
        // 取最小的两个元素组成一个树
        HuffmanTree left = _outQueue(&queue);
        HuffmanTree right = _outQueue(&queue);
        HuffmanTree node = createNode(' ', left->weights + right->weights);
        node->left = left;
        node->right = right;
        // 该树加入队列, 并在下次与最小的权重合并计算
        _priorityJoinQueue(&queue, node);
    }

    return _outQueue(&queue);
//    printf("%s\r\n", encoder(root, 'A'));
//    printf("%s\r\n", encoder(root, 'B'));
//    printf("%s\r\n", encoder(root, 'C'));
//    printf("%s\r\n", encoder(root, 'D'));
//    printf("%s\r\n", encoder(root, 'D'));
//    printf("%s\r\n", encoder(root, 'E'));
}

/**
 * @fun:   encoder
 * @data:  2022/10/5
 * @brief:
 * @param:
 * @ret:
 */
E *encoder(HuffmanTree root, E e)
{
    if (root == NULL) return NULL;
    if (root->elem == e) return "";

    E * str = encoder(root->left, e);
    E * s = malloc(sizeof(E) * 10);
    if (str != NULL)
    {
        s[0] = '0';
        str = strcat(s, str);
    }
    else
    {
        str = encoder(root->right, e);
        if (str != NULL)
        {
            s[0] = '1';
            str = strcat(s, str);
        }
    }
    return str;
}
#elif (selector == tree_4)

/**
 * @fun:   initHeap
 * @data:  2022/10/5
 * @brief: 堆初始化
 * @param:
 * @ret:
 */
_Bool initHeap(Heap heap)
{
    heap->size = 0;
    heap->capacity = 10;
    heap->arr = malloc(sizeof (E) * heap->capacity);
    return heap->arr != NULL;
}

/**
 * @fun:   insert
 * @data:  2022/10/5
 * @brief: 插入堆
 * @param:
 * @ret:
 */
_Bool insert(Heap heap, E element)
{
    if(heap->size == heap->capacity) return 0;   //满了就不处理了, 主要懒得写扩容了
    int index = ++heap->size;   //先计算出要插入的位置, 注意要先自增, 因为是从1开始的
    //然后开始向上堆化, 直到符合规则为止
    while (index > 1 && element > heap->arr[index / 2]) {
        heap->arr[index] = heap->arr[index / 2];
        index /= 2;
    }
    //现在得到的index就是最终的位置了
    heap->arr[index] = element;
    return 1;
}

/**
 * @fun:   delete
 * @data:  2022/10/5
 * @brief: 堆删除
 * @param:
 * @ret:
 */
E delete(Heap heap)
{
    E max = heap->arr[1], e = heap->arr[heap->size--];
    int index = 1;
    while (index * 2 <= heap->size) {   //从上往下找
        int child = index * 2;   //先找到左孩子
        //看看右孩子和左孩子哪个大, 先选一个大的出来
        if(child < heap->size && heap->arr[child] < heap->arr[child + 1])
            child += 1;
        if(e >= heap->arr[child]) break;   //如果子结点都不大于新结点, 那么说明就是这个位置, 结束就行了
        else heap->arr[index] = heap->arr[child];  //否则直接堆化, 换上去
        index = child;   //最后更新一下index到下面去
    }
    heap->arr[index] = e;   //找到合适位置后, 放进去就行了
    return max;
}

/**
 * @fun:   print
 * @data:  2022/10/5
 * @brief: 打印 Heap
 * @param:
 * @ret:
 */
void print(Heap heap)
{
    for (int i = 0; i < heap->size; i++)
    {
        printf("%d ", heap->arr[i]);
    }
    printf("\r\n");
}
#endif

Tree.h

#ifndef DATA_STRUCT_TREE_H
#define DATA_STRUCT_TREE_H

#include "main.h"

typedef char E;
typedef int I;
#if (selector != tree_1 && selector != tree_3)
typedef int T; // tmp
#endif

/** 二叉树 */
int countBinaryTreeNum(int nodesNum);
int completeBinaryTreeLeafNodesNum(int nodesNum);

#if(selector == tree_1)
/** 遍历 */
typedef struct BinaryTreeNode_t
{
    E elem;
    struct BinaryTreeNode_t *leftChild;
    struct BinaryTreeNode_t *rightChild;
    int flag;   // 用于后序&层序遍历
}*BinaryTree;
typedef BinaryTree T;

BinaryTree BinaryTreeBuild(BinaryTree leftChild, BinaryTree rightChild, E elem);
void BinaryTreePreOrderTraversal(BinaryTree tree);  // 递归
void BinaryTreePreOrder(BinaryTree tree);           // 栈
void BinaryTreeInorderTraversal(BinaryTree tree);   // 递归
void BinaryTreeInorder(BinaryTree tree);            // 栈
void BinaryTreePostOrderTraversal(BinaryTree tree); // 递归
void BinaryTreePostOrder(BinaryTree tree);          // 栈
//void BinaryTreeLevelOrderTraversal(BinaryTree tree);// 递归
void BinaryTreeLevelOrder(BinaryTree tree);         // 队列
#elif (selector == tree_1_1)
/** 线索二叉树 */
typedef struct TreeNode_t {
    E elem;
    struct TreeNode_t * leftChild;
    struct TreeNode_t * rightChild;
    struct TreeNode * parent;   //用于后续遍历, 指向双亲(父)节点
    int leftTag, rightTag;   //标志位, 如果为1表示这一边指针指向的是线索, 不为1就是正常的子节点
} *TreeNode;

TreeNode buildNode(E elem);
TreeNode preInit();

void preOrderThreaded(TreeNode root);
void preOrder(TreeNode root);
void inOrderThreaded(TreeNode root);
void inOrder(TreeNode root);
void postOrderThreaded(TreeNode root);
void postOrder(TreeNode root);

#elif (selector == tree_1_2)
/** 二叉查找树 */
typedef struct TreeNode {
    E elem;
    struct TreeNode *left;
    struct TreeNode *right;
}* Node;

Node buildNode(E elem);
Node insertNode(Node root, E elem);
Node searchNode(Node root, E target);
Node maxNode(Node root)
Node minNode(Node root)

#elif (selector == tree_1_3)
/** 平衡二叉树 */
typedef struct TreeNode {
    I element;
    struct TreeNode * left;
    struct TreeNode * right;
    int height;   // 每个节点需要记录当前子树的高度,便于计算平衡因子
} * Node;

I max(I e1, I e2);
int getHeight(Node root);
Node leftRotation(Node root);
Node rightRotation(Node root);
Node leftRightRotation(Node root);
Node rightLeftRightRotation(Node root);
Node insert(Node root, I element);
/** 红黑树 */

#elif (selector == tree_2)
/** B树 & B+树 */


#elif (selector == tree_3)
/** 哈夫曼树 */
typedef struct HuffmanTree_t {
  E elem;
  struct HuffmanTree_t *left;
  struct HuffmanTree_t *right;
  int weights;
}*HuffmanTree;

typedef HuffmanTree T;

HuffmanTree createNode(E elem, int weights);
HuffmanTree buildHuffmanTree(char alpha[], int weights[], int size);
E *encoder(HuffmanTree root, E e);

#elif (selector == tree_4)
/** 堆和优先队列 */
typedef struct MaxHeap {
    E * arr;
    int size;
    int capacity;
} * Heap;

_Bool initHeap(Heap heap);
_Bool insert(Heap heap, E element);
E delete(Heap heap);
void print(Heap heap);
#endif


#endif //DATA_STRUCT_TREE_H

散列

Hash.c

#include "Hash.h"
#include <malloc.h>


#if (selector == hash_1)

/**
 * @fun:   initHash
 * @data:  2022/10/5
 * @brief: 初始化哈希表
 * @param:
 * @ret:
 */
void initHash(HashTable table)
{
    table->table = malloc(sizeof(Element) * SIZE);
    for (int i = 0; i < SIZE; i++)
        table->table[i] = NULL;
}

/**
 * @fun:   createElement
 * @data:  2022/10/5
 * @brief: 创建元素
 * @param:
 * @ret:
 */
Element createElement(int key)
{
    Element elem = malloc(sizeof(Element));
    elem->key = key;
    return elem;
}

/**
 * @fun:   Hash
 * @data:  2022/10/5
 * @brief: 哈希函数
 * @param:
 * @ret:
 */
int hash(int key)
{
    return key % SIZE;
}

/**
 * @fun:   insertHash
 * @data:  2022/10/5
 * @brief: 插入哈希表
 * @param:
 * @ret:
 */
void insertHash(HashTable table, Element elem)
{
    int hashVal = hash(elem->key);
    table->table[hashVal] = elem;
}

/**
 * @fun:   searchHash
 * @data:  2022/10/5
 * @brief: 搜索哈希值
 * @param:
 * @ret:
 */
Element searchHash(HashTable table, int key)
{
    int hashVal = hash(key);
    if (table->table[hashVal] == NULL) return NULL;
    return table->table[hashVal]->key == key ? table->table[hashVal] : NULL;
}


//#elif (selector == hash_1_1)
/** 线性探测法 防止 哈希碰撞 */
/**
 * @fun:   insertHash_LD
 * @data:  2022/10/5
 * @brief: 线性探测法插入哈希表
 * @param:
 * @ret:
 */
void insertHash_LD(HashTable table, Element elem)
{
    int hashVal = hash(elem->key);
    int cnt = 0;
    // 若哈希冲突则位移寻找空余
    while (table->table[hashVal])
    {
        hashVal = hash(elem->key + ++cnt);
        if (cnt >= SIZE) return; // 满
    }
    table->table[hashVal] = elem;
}

/**
 * @fun:   searchHash_LD
 * @data:  2022/10/5
 * @brief: 线性探测法搜索哈希值
 * @param:
 * @ret:
 */
Element searchHash_LD(HashTable table, int key)
{
    int hashVal = hash(key);
    int cnt = 0;
    const int startIndex = hashVal; // 记录初始值
    do {
        if (table->table[hashVal]->key == key) return table->table[hashVal];
        hashVal = hash(key + ++cnt);
    } while (startIndex != hashVal && table->table[hashVal]);

    return NULL;
}

/**
 * @fun:   deleteHash_LD
 * @data:  2022/10/5
 * @brief: 删除哈希元素, 并要打上标记
 * @param:
 * @ret:
 */
void deleteHash_LD(HashTable table, int key)
{
    int hashVal = hash(key);
    int cnt = 0;
    const int startIndex = hashVal; // 记录初始值
    do {
        if (table->table[hashVal]->key == key) { table->table[hashVal]->key = key + SIZE; return;}
        hashVal = hash(key + ++cnt);
    } while (startIndex != hashVal && table->table[hashVal]);
}
#elif (selector == hash_1_2)
/** 链地址法 防止 哈希碰撞 */

/**
 * @fun:   initHashTable
 * @data:  2022/10/5
 * @brief:
 * @param:
 * @ret:
 */
void initHashTable(HashTable hashTable)
{
    hashTable->table = malloc(sizeof(struct ListNode) * SIZE);// should not sizeof(Node)
    for (int i = 0; i < SIZE; ++i) {
        hashTable->table[i].key = -1;   //将头结点key置为-1, next指向NULL
        hashTable->table[i].next = NULL;
    }
}

/**
 * @fun:   hash
 * @data:  2022/10/5
 * @brief: 哈希函数
 * @param:
 * @ret:
 */
int hash(int key)
{
    return key % SIZE;
}

/**
 * @fun:   createNode
 * @data:  2022/10/5
 * @brief: 创建节点
 * @param:
 * @ret:
 */
Node createNode(int key)
{
    Node node = malloc(sizeof(Node));
    node->key = key;
    node->next = NULL;
    return node;
}

/**
 * @fun:   insertHash
 * @data:  2022/10/5
 * @brief:
 * @param:
 * @ret:
 */
void insertHash(HashTable hashTable, int key)
{
    int hashVal = hash(key);
    Node head = hashTable->table + hashVal;   //先计算哈希值, 找到位置后直接往链表后面插入结点
    while (head->next) head = head->next;
    head->next = createNode(key);   //插入新的结点
}

/**
 * @fun:   searchHash
 * @data:  2022/10/5
 * @brief:
 * @param:
 * @ret:
 */
_Bool searchHash(HashTable hashTable, int key)
{
    int hashVal = hash(key);
    Node head = hashTable->table + hashVal;
    while (head->next && head->key != key)   //直到最后或是找到为止
        head = head->next;
    return head->key == key;   //直接返回是否找到
}

#endif

Hash.h

#ifndef DATA_STRUCT_HASH_H
#define DATA_STRUCT_HASH_H

#include "main.h"

#if (selector == hash_1)
#define SIZE 100

typedef struct Element_t {
    int key;
}* Element;

typedef struct HashTable_t {
    Element * table;
} * HashTable;

void initHash(HashTable table);
Element createElement(int key);
int hash(int key);
void insertHash(HashTable table, Element elem);
Element searchHash(HashTable table, int key);
//#elif (selector == hash_1_1)
void insertHash_LD(HashTable table, Element elem);
Element searchHash_LD(HashTable table, int key);
#elif (selector == hash_1_2)
#define SIZE 9

typedef struct ListNode {   //结点定义
    int key;
    struct ListNode * next;
} * Node;

typedef struct HashTable{   //哈希表
    struct ListNode * table;   //这个数组专门保存头结点
} * HashTable;

void initHashTable(HashTable hashTable);
int hash(int key);
Node createNode(int key);
void insertHash(HashTable hashTable, int key);
_Bool searchHash(HashTable hashTable, int key);
#endif

#endif //DATA_STRUCT_HASH_H

Graph.c

#include "Graph.h"
#include <malloc.h>

#if (selector == graph_1)
    /** 4.1 邻接矩阵 */
/**
 * @fun:   create
 * @data:  2022/10/6
 * @brief: 创建图
 * @param:
 * @ret:
 */
MatrixGraph create()
{
    MatrixGraph graph = malloc(sizeof(struct MatrixGraph_t));
    graph->vertexCount = 0;    //顶点和边数肯定一开始是0
    graph->edgeCount = 0;
    for (int i = 0; i < MaxVertex; ++i)    //记得把矩阵每个位置都置为0
        for (int j = 0; j < MaxVertex; ++j)
            graph->matrix[i][j] = 0;
    return graph;
}

/**
 * @fun:   addVertex
 * @data:  2022/10/6
 * @brief: 添加元素
 * @param:
 * @ret:
 */
void addVertex(MatrixGraph graph, E element){
    if(graph->vertexCount >= MaxVertex) return;
    graph->data[graph->vertexCount++] = element;   //添加新元素
}

/**
 * @fun:   addEdge
 * @data:  2022/10/6
 * @brief: 添加顶点的边
 * @param:
 * @ret:
 */
void addEdge(MatrixGraph graph, int a, int b)
{
    if(graph->matrix[a][b] == 0) {
        graph->matrix[a][b] = 1;  //注意如果是无向图的话, 需要[a][b]和[b][a]都置为1
        graph->edgeCount++;
    }
}

/**
 * @fun:   printGraph
 * @data:  2022/10/6
 * @brief: 打印
 * @param:
 * @ret:
 */
void printGraph(MatrixGraph graph)
{
    for (int i = -1; i < graph->vertexCount; ++i) {
        for (int j = -1; j < graph->vertexCount; ++j) {
            if(j == -1)
                printf("%c", 'A' + i);
            else if(i == -1)
                printf("%3c", 'A' + j);
            else
                printf("%3d", graph->matrix[i][j]);
        }
        putchar('\n');
    }
}
#elif (selector == graph_2 || selector == graph_3 || selector == graph_4)
/** 4.2 邻接表 */

/* *
 * @fun:   create
 * @data:  2022/10/6
 * @brief: 创建
 * @param:
 * @ret:
 */
AdjacencyGraph create()
{
    AdjacencyGraph graph = malloc(sizeof(struct AdjacencyGraph_t));
    graph->vertexCount = graph->edgeCount = 0;
    return graph;   //头结点数组一开始可以不用管
}

/**
 * @fun:   addVertex
 * @data:  2022/10/6
 * @brief: 添加元素
 * @param:
 * @ret:
 */
void addVertex(AdjacencyGraph graph, E element)
{
    if(graph->vertexCount >= MaxVertex) return;
    graph->vertex[graph->vertexCount].element = element;   //添加新结点时, 再来修改也行
    graph->vertex[graph->vertexCount].next = NULL;
    graph->vertexCount++;
}

/**
 * @fun:   addEdge
 * @data:  2022/10/6
 * @brief: 添加边
 * @param:
 * @ret:
 */
void addEdge(AdjacencyGraph graph, int a, int b)
{
    Node node = graph->vertex[a].next;
    Node newNode = malloc(sizeof(struct Node));
    newNode->next = NULL;
    newNode->nextVertex = b;
    if(!node) {    //如果头结点下一个都没有, 那么直接连上去
        graph->vertex[a].next = newNode;
    } else {   //否则说明当前顶点已经连接了至少一个其他顶点了, 有可能会出现已经连接过的情况, 所以要特别处理一下
        do {
            if(node->nextVertex == b) return;   //如果已经连接了对应的顶点, 那么直接返回
            if(node->next) node = node->next;   //否则继续向后遍历
            else break;   //如果没有下一个了, 那就找到最后一个结点了, 直接结束
        } while (1);
        node->next = newNode;
    }
    graph->edgeCount++;   //边数计数+1
}

/**
 * @fun:   printGraph
 * @data:  2022/10/6
 * @brief: 打印
 * @param:
 * @ret:
 */
void printGraph(AdjacencyGraph graph)
{
    for (int i = 0; i < graph->vertexCount; ++i) {
        printf("%d | %c", i, graph->vertex[i].element);
        Node node = graph->vertex[i].next;
        while (node) {
            printf(" -> %d", node->nextVertex);
            node = node->next;
        }
        putchar('\n');
    }
}
//#elif (selector == graph_3)
    /** 4.3 深度优先 */

/**
 * @fun:   dfs
 * @data:  2022/10/6
 * @brief: 深度优先
 * @param: graph
 * @param: startVertex
 * @param: targetVertex
 * @param: visited
 * @ret:
 */
void dfs(AdjacencyGraph graph, int startVertex, int targetVertex, int * visited)
{
    visited[startVertex] = 1;   //走过之后一定记得mark一下
    printf("%c -> ", graph->vertex[startVertex].element);   //打印当前顶点值
    Node node = graph->vertex[startVertex].next;   //遍历当前顶点所有的分支
    while (node) {
        if(!visited[node->nextVertex])   //如果已经到过(有可能是走其他分支到过,或是回头路)那就不继续了
            dfs(graph, node->nextVertex, targetVertex, visited);  //没到过就继续往下走,这里将startVertex设定为对于分支的下一个顶点,按照同样的方式去寻找
        node = node->next;
    }
}
//#elif (selector == graph_4)
    /** 4.4 广度优先 */

/**
 * @fun:   bfs
 * @data:  2022/10/6
 * @brief: 广度优先
 * @param:
 * @ret:
 */
void bfs(AdjacencyGraph graph, int startVertex, int targetVertex, int * visited, _LinkedQueue queue) {
    _offerQueue(queue, startVertex);  //首先把起始位置顶点丢进去
    visited[startVertex] = 1;   //起始位置设置为已走过
    while (!_isEmpty(queue)) {
        int next = _pollQueue(queue);
        printf("%c -> ", graph->vertex[next].element);  //从队列中取出下一个顶点,打印
        Node node = graph->vertex[next].next;    //同样的,把每一个分支都遍历一下
        while (node) {
            if(!visited[node->nextVertex]) {   //如果没有走过,那么就直接入队
                _offerQueue(queue, node->nextVertex);
                visited[node->nextVertex] = 1;   //入队时就需要设定为1了
            }
            node = node->next;
        }
    }
}

extern void bfs(AdjacencyGraph graph, int startVertex, int targetVertex, int * visited, _LinkedQueue queue);


#elif (selector == graph_5)
    /** 4.5 生成树 & 最小生成树  */

#elif (selector == graph_6)
    /** 4.6 单源最短路径 & 顶点最短路径 */

#elif (selector == graph_7)
    /** 4.7 拓扑排序 */

#elif (selector == graph_8)
    /** 4.8 关键路径 */

#endif

Graph.h

#ifndef DATA_STRUCT_GRAPH_H
#define DATA_STRUCT_GRAPH_H

#include "main.h"
#include "_Queue.h"

#if (selector == graph_1)
/** 4.1 邻接矩阵 */
#define MaxVertex 5

typedef char E;   //顶点存放的数据类型

typedef struct MatrixGraph_t {
    int vertexCount;   //顶点数
    int edgeCount;     //边数
    int matrix[MaxVertex][MaxVertex];   //邻接矩阵
    E data[MaxVertex];    //各个顶点对应的数据
} * MatrixGraph;

MatrixGraph create();
void addVertex(MatrixGraph graph, E element);
void addEdge(MatrixGraph graph, int a, int b);
void printGraph(MatrixGraph graph);

#elif (selector == graph_2 || selector == graph_3 || selector == graph_4)

/** 4.2 邻接表 */
#define MaxVertex 5

typedef char E;

typedef struct Node {   //结点和头结点分开定义,普通结点记录邻接顶点信息
    int nextVertex;
    struct Node * next;
} * Node;

struct HeadNode {   //头结点记录元素
    E element;
    struct Node * next;
};

typedef struct AdjacencyGraph_t {
    int vertexCount;   //顶点数
    int edgeCount;     //边数
    struct HeadNode vertex[MaxVertex];
} * AdjacencyGraph;

AdjacencyGraph create();
void addVertex(AdjacencyGraph graph, E element);
void addEdge(AdjacencyGraph graph, int a, int b);
void printGraph(AdjacencyGraph graph);

//#elif (selector == graph_3)
    /** 4.3 深度优先 */
void dfs(AdjacencyGraph graph, int startVertex, int targetVertex, int * visited);
//#elif (selector == graph_4)
    /** 4.4 广度优先 */
//bfs(AdjacencyGraph graph, int startVertex, int targetVertex, int * visited, _LinkedQueue queue);
#elif (selector == graph_5)
    /** 4.5 生成树 & 最小生成树  */

#elif (selector == graph_6)
    /** 4.6 单源最短路径 & 顶点最短路径 */

#elif (selector == graph_7)
    /** 4.7 拓扑排序 */

#elif (selector == graph_8)
    /** 4.8 关键路径 */

#endif

#endif //DATA_STRUCT_GRAPH_H

排序

Sort.c

#include <malloc.h>
#include "Sort.h"

void swap(int * a, int * b){
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

#if (selector == sort_1)
/** 5.1 冒泡  */
int *Bubble(int arr[], int size)
{
    for (int i = 0; i < size - 1; i++)
    {
        _Bool flag = 1;
        for (int j = i + 1; j < size; j++)
        {
            if (arr[i] > arr[j]) {int temp = arr[j]; arr[j] = arr[i]; arr[i] = temp; flag = 0;}
        }
        if(flag) break;
    }
    return arr;
}
#elif (selector == sort_2)
/** 5.2 插入  */
void * insertSort(int arr[], int size)
{
    for (int i = 1; i < size; i++)
    {
        int j = i, tmp = arr[i];
        // 向后找对应的位置插入
        while(j > 0 && arr[j - 1] > tmp)
        {
            arr[j] = arr[j - 1];
            j--;
        }
        arr[j] = tmp;
    }
    return arr;
}
#elif (selector == sort_3)
    /** 5.3 选择  */
//int *selectSort(int arr[], int size)
//{
//    for (int i = 0; i < size - 1; ++i) {   //因为最后一个元素一定是在对应位置上的, 所以只需要进行N - 1轮排序
//        int min = i;   //记录一下当前最小的元素, 默认是剩余元素中的第一个元素
//        for (int j = i + 1; j < size; ++j)   //挨个遍历剩余的元素, 如果遇到比当前记录的最小元素还小的元素, 就更新
//            if(arr[min] > arr[j])
//                min = j;
//        int tmp = arr[i];    //找出最小的元素之后, 开始交换
//        arr[i] = arr[min];
//        arr[min] = tmp;
//    }
//    return arr;
//}

int * selectSort(int arr[], int size)
{
    int left = 0, right = size - 1;   //相当于左端和右端都是已经排好序的,中间是待排序的,所以说范围不断缩小
    while (left < right) {
        int min = left, max = right;
        for (int i = left; i <= right; i++) {
            if (arr[i] < arr[min]) min = i;   //同时找最小的和最大的
            if (arr[i] > arr[max]) max = i;
        }
        swap(&arr[max], &arr[right]);   //这里先把大的换到右边
        //注意大的换到右边之后, 有可能被换出来的这个就是最小的, 所以需要判断一下
        //如果遍历完发现最小的就是当前右边排序的第一个元素
        //此时因为已经被换出来了, 所以说需要将min改到换出来的那个位置
        if (min == right) min = max;
        swap(&arr[min], &arr[left]);   //接着把小的换到左边
        left++;    //这一轮完后, 缩小范围
        right--;
    }
    return arr;
}
#elif (selector == sort_4)
    /** 5.4 快排  */
    int * quickSort(int arr[], int start, int end)
    {
        if(start >= end) return arr;    //范围不可能无限制的划分下去, 要是范围划得都没了, 肯定要结束了
        int left = start, right = end, pivot = arr[left];   //这里我们定义两个指向左右两个端点的指针, 以及取出基准
        while (left < right) {     //只要两个指针没相遇, 就一直循环进行下面的操作
            while (left < right && arr[right] >= pivot) right--;   //从右向左看, 直到遇到比基准小的
            arr[left] = arr[right];    //遇到比基准小的, 就丢到左边去
            while (left < right && arr[left] <= pivot) left++;   //从左往右看, 直到遇到比基准大的
            arr[right] = arr[left];    //遇到比基准大的, 就丢到右边去
        }
        arr[left] = pivot;    //最后相遇的位置就是基准存放的位置了
        quickSort(arr, start, left - 1);   //不包含基准, 划分左右两边, 再次进行快速排序
        quickSort(arr, left + 1, end);
        return arr;
    }
#elif (selector == sort_5)
    /** 5.5 希尔  */
int * shellSort(int arr[], int size)
{
    int delta = size / 2;
    while (delta >= 1) {
        //这里依然是使用之前的插入排序, 不过此时需要考虑分组了
        for (int i = delta; i < size; ++i) {   //我们需要从delta开始, 因为前delta个组的第一个元素默认是有序状态
            int j = i, tmp = arr[i];   //这里依然是把待插入的先抽出来
            while (j >= delta && arr[j - delta] > tmp) {
                //注意这里比较需要按步长往回走, 所以说是j - delta, 此时j必须大于等于delta才可以, 如果j - delta小于0说明前面没有元素了
                arr[j] = arr[j - delta];
                j -= delta;
            }
            arr[j] = tmp;
        }
        delta /= 2;    //分组插排完事之后, 重新计算步长
    }
    return arr;
}
#elif (selector == sort_6)
    /** 5.6 堆  */

_Bool initHeap(Heap heap, int size)
{
    heap->size = 0;
    heap->capacity = size;
    heap->arr = malloc(sizeof (E) * heap->capacity);
    return heap->arr != NULL;
}

_Bool insertHeap(Heap heap, E element)
{
    if(heap->size == heap->capacity) return 0;
    int index = ++heap->size;
    while (index > 1 && element < heap->arr[index / 2]) {
        heap->arr[index] = heap->arr[index / 2];
        index /= 2;
    }
    heap->arr[index] = element;
    return 1;
}

E deleteHeap(Heap heap)
{
    E max = heap->arr[1], e = heap->arr[heap->size--];
    int index = 1;
    while (index * 2 <= heap->size) {
        int child = index * 2;
        if(child < heap->size && heap->arr[child] > heap->arr[child + 1])
            child += 1;
        if(e <= heap->arr[child]) break;
        else heap->arr[index] = heap->arr[child];
        index = child;
    }
    heap->arr[index] = e;
    return max;
}


//这个函数就是对start顶点位置的子树进行堆化
void makeHeap(int* arr, int start, int end)
{
    while (start * 2 + 1 <= end) {    //如果有子树,就一直往下,因为调整之后有可能子树又不满足性质了
        int child = start * 2 + 1;    //因为下标是从0开始,所以左孩子下标就是i * 2 + 1,右孩子下标就是i * 2 + 2
        if(child + 1 <= end && arr[child] < arr[child + 1])   //如果存在右孩子且右孩子比左孩子大
            child++;    //那就直接看右孩子
        if(arr[child] > arr[start])   //如果上面选出来的孩子,比父结点大,那么就需要交换,大的换上去,小的换下来
            swap(&arr[child], &arr[start]);
        start = child;   //继续按照同样的方式前往孩子结点进行调整
    }
}

int * heapSort(int arr[], int size)
{
    for(int i= size/2 - 1; i >= 0; i--)   //我们首选需要对所有非叶子结点进行一次堆化操作,需要从最后一个到第一个,这里size/2计算的位置刚好是最后一个非叶子结点
        makeHeap(arr, i, size - 1);
    for (int i = size - 1; i > 0; i--) {   //接着我们需要一个一个把堆顶元素搬到后面,有序排列
        swap(&arr[i], &arr[0]);    //搬运实际上就是直接跟倒数第i个元素交换,这样,每次都能从堆顶取一个最大的过来
        makeHeap(arr, 0, i - 1);   //每次搬运完成后,因为堆底元素被换到堆顶了,所以需要再次对根结点重新进行堆化
    }
    return arr;
}
#elif (selector == sort_7)
    /** 5.7 归并  */
void merge(int arr[], int tmp[], int left, int leftEnd, int right, int rightEnd)
{
    int i = left, size = rightEnd - left + 1;   //这里需要保存一下当前范围长度,后面使用
    while (left <= leftEnd && right <= rightEnd) {   //如果两边都还有, 那么就看哪边小, 下一个就存哪一边的
        if(arr[left] <= arr[right])   //如果左边的小, 那么就将左边的存到下一个位置(这里i是从left开始的)
            tmp[i++] = arr[left++];   //操作完后记得对i和left都进行自增
        else
            tmp[i++] = arr[right++];
    }
    while (left <= leftEnd)    //如果右边看完了, 只剩左边, 直接把左边的存进去
        tmp[i++] = arr[left++];
    while (right <= rightEnd)   //同上
        tmp[i++] = arr[right++];
    for (int j = 0; j < size; ++j, rightEnd--)   //全部存到暂存空间中之后, 暂存空间中的内容都是有序的了, 此时挨个搬回原数组中(注意只能搬运范围内的)
        arr[rightEnd] = tmp[rightEnd];
}

int * mergeSort(int arr[], int tmp[], int start, int end)
{
    //要进行归并排序需要提供数组和原数组大小的辅助空间
    if(start >= end) return arr;   //依然是使用递归, 所以说如果范围太小, 就不用看了
    int mid = (start + end) / 2;   //先找到中心位置, 一会分两半
    mergeSort(arr, tmp, start, mid);   //对左半和右半分别进行归并排序
    mergeSort(arr, tmp, mid + 1, end);
    merge(arr, tmp, start, mid, mid + 1, end);
  	//上面完事之后, 左边和右边都是有序状态了, 此时再对整个范围进行一次归并排序即可
    return arr;
}
#elif (selector == sort_8)
    /** 5.8 计数  */

#elif (selector == sort_9)
    /** 5.9 桶  */

#elif (selector == sort_10)
    /** 5.10 基数  */

#endif

Sort.h

#ifndef DATA_STRUCT_SORT_H
#define DATA_STRUCT_SORT_H

#include "main.h"

#if (selector == sort_1)
/** 5.1 冒泡  */
int *Bubble(int arr[], int size);
#elif (selector == sort_2)
/** 5.2 插入  */
void * insertSort(int arr[], int size);

#elif (selector == sort_3)
    /** 5.3 选择  */
int *selectSort(int arr[], int size);
#elif (selector == sort_4)
    /** 5.4 快排  */
int * quickSort(int arr[], int start, int end);
#elif (selector == sort_5)
    /** 5.5 希尔  */
int * shellSort(int arr[], int size);
#elif (selector == sort_6)
    /** 5.6 堆  */
typedef int E;
typedef struct MinHeap {
    E * arr;
    int size;
    int capacity;
} * Heap;

_Bool initHeap(Heap heap, int size);
_Bool insertHeap(Heap heap, E element);
E deleteHeap(Heap heap);
void makeHeap(int* arr, int start, int end);
int * heapSort(int arr[], int size);

#elif (selector == sort_7)
    /** 5.7 归并  */
void merge(int arr[], int tmp[], int left, int leftEnd, int right, int rightEnd);
int * mergeSort(int arr[], int tmp[], int start, int end);
#elif (selector == sort_8)
    /** 5.8 计数  */

#elif (selector == sort_9)
    /** 5.9 堆  */

#elif (selector == sort_10)
    /** 5.10 基数  */

#endif

#endif //DATA_STRUCT_SORT_H

二分搜索

_BinarySearch.c

#include <stdio.h>
#include "_BinarySearch.h"

int binarySearch(int arr[], int len, int target)
{
    int max = len, min = 0;
    while (max >= min)
    {
        int index = ((max - min) / 2 > min) ? ((max - min) / 2) : min;
        printf("%d %d index %d\r\n", max, min, index);
        if (arr[index] > target) { max = index - 1; }
        else if (arr[index] < target) { min = index + 1; }
        else return index;
    }
    return -1;
}

_BinarySearch.h

#ifndef DATA_STRUCT__BINARYSEARCH_H
#define DATA_STRUCT__BINARYSEARCH_H
int binarySearch(int arr[], int len, int target);
#endif //DATA_STRUCT__BINARYSEARCH_H

CMakeList.txt

cmake_minimum_required(VERSION 3.20)
project(Data_Struct C)

set(CMAKE_C_STANDARD 99)

add_executable(Data_Struct main.c _BinarySearch.c _BinarySearch.h SeqList.c SeqList.h Tree.c Tree.h _Stack.c _Stack.h _Queue.c _Queue.h Hash.c Hash.h Graph.c Graph.h Sort.c Sort.h)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值