常用数据结构算法C语言实现

426 阅读17分钟

咱本地编译过了、保证OK

github地址:github.com/nppp1990/st…

排序算法

冒泡排序

#include <stdio.h>

void bubbleSort(int arr[], int len) {
    int i, j, temp;
    int flag;
    for (i = 0; i < len - 1; i++) {
        flag = 0;
        for (j = 0; j < len - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                flag = 1;
            }
        }
        if (flag == 0) {
            // 说明没有需要交换的数,说明所有的数已排序
            return;
        }
    }
}

void testBubbleSort() {
    printf("\n-----bubbleSort-----begin\n");
    int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };
    int len = (int) sizeof(arr) / sizeof(*arr);
    bubbleSort(arr, len);
    int i;
    for (i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n-----bubbleSort-----end\n");
}

选择排序

#include <stdio.h>

void selectSort(int arr[], int len) {
    int i, j, temp;
    for (i = 0; i < len - 1; i++) {
        int min = i;
        for (j = i + 1; j < len; j++) {
            if (arr[j] < arr[min]) {
                //记录最小值的位置
                min = j;
            }
        }
        //最小值和i交换
        temp = arr[min];
        arr[min] = arr[i];
        arr[i] = temp;
    }
}

void testSelectSort() {
    printf("\n-----selectSort-----begin\n");
    int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
    int len = (int) sizeof(arr) / sizeof(*arr);
    selectSort(arr, len);
    int i;
    for (i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n-----selectSort-----end\n");
}

插入排序

#include <stdio.h>

void insertSort(int arr[], int len) {
    int i, j, key;
    for (i = 1; i < len; i++) {
        key = arr[i];
        j = i - 1;
        while ((j >= 0) && (arr[j] > key)) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

void testInsertSort() {
    printf("\n-----insertSort-----begin\n");
    int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
    int len = (int) sizeof(arr) / sizeof(*arr);
    insertSort(arr, len);
    int i;
    for (i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n-----insertSort-----begin\n");
}

快速排序

#include <stdio.h>

int quickSort(int arr[], int left, int right) {
    if (left >= right) {
        // 递归结束的条件
        return 0;
    }

    // 指针p指向left
    int p = arr[left];
    int i = left;
    int j = right;
    while (i < j) {
        while (i < j && arr[j] >= p) {
            // 从最右往左找到第一个小于p的位置j
            j--;
        }
        while (i < j && arr[i] <= p) {
            // 从左往右找到第一个大于p的位置i
            i++;
        }
        if (i < j) {
            // 交换i和j
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }

    // i和j相遇,说明temp的左边的数都小于等于temp;右边都大于等于temp
    int temp = arr[i];
    arr[i] = arr[left];
    arr[left] = temp;

    // temp位置已确定,递归快排剩余的数
    quickSort(arr, left, i - 1);
    quickSort(arr, j + 1, right);
}


void testQuickSort() {
    printf("\n-----quickSort-----begin\n");
    int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
    int len = (int) sizeof(arr) / sizeof(*arr);
    quickSort(arr, 0, len - 1);
    int i;
    for (i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n-----quickSort-----end\n");
}

堆排序

#include <stdio.h>

//交换
void heapSwap(int arr[], int i, int j) {
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

// 自下而上的建堆方法
void maxHeapify(int arr[], int length) {
    int i = length / 2 - 1;
    while (i >= 0) {
        int left = i * 2 + 1;
        int right = i * 2 + 2;
        int max; // 左右孩子中最大的数
        if (right < length && arr[left] < arr[right]) {
            max = right;
        } else {
            max = left;
        }
        if (arr[i] < arr[max]) {
            // 如果左右孩子中最大的数大于i,则把大的数和i交换
            heapSwap(arr, i, max);
        }
        i--;
    }
}

void insertHeap(int arr[], int length) {
    for (int i = 1; i < length; i++) {
        int currentIndex = i;
        int fatherIndex = (i - 1) / 2;
        while (currentIndex >= 1 && arr[fatherIndex] < arr[currentIndex]) {
            heapSwap(arr, fatherIndex, currentIndex);
            currentIndex = fatherIndex;
            fatherIndex = (currentIndex - 1) / 2;
        }
    }
}

void correctHeap(int arr[], int size) {
    int index = 0;
    while (index * 2 + 1 < size) {
        // 至少有一个左孩子
        int left = index * 2 + 1; // 左子孩子
        int right = index * 2 + 2; // 右子孩子
        int max;
        if (right < size && arr[left] < arr[right]) {
            max = right;
        } else {
            max = left;
        }

        if (arr[index] >= arr[max]) {
            return;
        }
        heapSwap(arr, index, max);
        index = max;
    }
}

/**
 * 自下而上的堆排序 建堆复杂度O(n)
 * @param arr
 * @param length
 */
void heapSort1(int arr[], int length) {
    maxHeapify(arr, length);
    int size = length;
    while (size > 1) {
        // 交换堆顶和数组尾部的数、固定最大值
        heapSwap(arr, 0, size - 1);
        size--;
        // 纠正大顶堆
        maxHeapify(arr, size);
    }

}

/**
 * 自上而下、插入法的堆排序 建堆复杂度O(nlogn)
 * @param arr
 * @param length
 */
void heapSort2(int arr[], int length) {
    // 用从上往下遍历插入的方式构造大顶堆
    insertHeap(arr, length);
    int size = length;
    while (size > 1) {
        // 交换堆顶和数组尾部的数、固定最大值
        heapSwap(arr, 0, size - 1);
        size--;
        // 纠正大顶堆
        correctHeap(arr, size);
    }
}

void testHeapSort() {
    int arr1[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
    int arr2[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
    int len = (int) sizeof(arr1) / sizeof(*arr1);
    printf("\n-----heapSort:自下而上-----begin\n");
    heapSort1(arr1, len);
    int i;
    for (i = 0; i < len; i++) {
        printf("%d ", arr1[i]);
    }
    printf("\n-----heapSort:自下而上-----end\n");

    printf("\n-----heapSort:自上而下-----begin\n");
    heapSort2(arr2, len);
    for (i = 0; i < len; i++) {
        printf("%d ", arr2[i]);
    }
    printf("\n-----heapSort:自上而下-----end\n");
}

归并排序

#include <stdio.h>

void merge(int arr[], int low, int mid, int high) {
    int length = high - low + 1;
    int temp[length];
    int i = low;
    int j = mid + 1;
    int k = 0;
    // 把较小的数先移到新数组中
    while (i <= mid && j <= high) {
        if (arr[i] < arr[j]) {
            temp[k++] = arr[i++];
        } else {
            temp[k++] = arr[j++];
        }
    }
    // 把左边剩余的数移入数组
    while (i <= mid) {
        temp[k++] = arr[i++];
    }
    // 把右边边剩余的数移入数组
    while (j <= high) {
        temp[k++] = arr[j++];
    }

    for (i = low; i <= high; i++) {
        arr[i] = temp[i - low];
    }
}

void mergeSort(int arr[], int low, int high) {
    int mid = (low + high) / 2;
    if (low < high) {
        mergeSort(arr, low, mid);
        mergeSort(arr, mid + 1, high);
        //左右归并
        merge(arr, low, mid, high);
    }
}

void testMergeSort() {
    printf("\n-----mergeSort-----begin\n");
    int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
    int len = (int) sizeof(arr) / sizeof(*arr);
    mergeSort(arr, 0, len - 1);
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n-----mergeSort-----end\n");
}

希尔排序

#include <stdio.h>

void shellSort(int arr[], int length) {
    int gap;
    for (gap = length / 2; gap > 0; gap /= 2) {
        // 分组插入排序
        for (int i = 0; i < gap; i++) {
            for (int j = i + gap; j < length; j += gap) {
                int key = arr[j];
                int k = j - gap;
                while (k >= i && arr[k] > key) {
                    arr[k + gap] = arr[k];
                    k -= gap;
                }
                arr[k + gap] = key;
            }
        }
    }
}


void testShellSort() {
    printf("\n-----shellSort-----begin\n");

    int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
    int len = (int) sizeof(arr) / sizeof(*arr);
    shellSort(arr, len);
    int i;
    for (i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n-----shellSort-----begin\n");
}

基数排序

#include <stdlib.h>
#include <printf.h>

typedef struct RadixNode {
    int data;
    struct RadixNode *next;
} RadixNode;

struct RadixNode *creatRadixNode(int value) {
    RadixNode *node = (RadixNode *) malloc(sizeof(RadixNode));
    node->next = NULL;
    node->data = value;
    return node;
}

#define MOD 10

void radixSort(int arr[], int len, int maxDigit) {
    RadixNode **buckets = (RadixNode **) malloc(sizeof(RadixNode *) * MOD);
    // 存储链表尾部,用来模拟队列
    RadixNode **tailBuckets = (RadixNode **) malloc(sizeof(RadixNode *) * MOD);
    for (int i = 0; i < MOD; i++) {
        // 创建头结点
        struct RadixNode *node = creatRadixNode(-1);
        buckets[i] = node;
        tailBuckets[i] = node;
    }

    int index;
    RadixNode *head, *next, *temp;
    for (int i = 0, radix = 1; i < maxDigit; i++, radix *= MOD) {
        for (int j = 0; j < len; j++) {
            index = arr[j] / radix % MOD;
            // 尾部插入arr[j]
            temp = creatRadixNode(arr[j]);
            tailBuckets[index]->next = temp;
            tailBuckets[index] = temp;
        }

        int k = 0;
        for (int j = 0; j < 10; ++j) {
            // 遍历buckets数据,按照先进先出的方式取出链表数据,所以这里应该用队列来实现
            RadixNode *p = buckets[j]->next;
            while (p) {
                arr[k++] = p->data;
                temp = p->next;
                free(p);
                p = temp;
            }
            // 重置buckets和tailBuckets
            buckets[j]->next = NULL;
            tailBuckets[j] = buckets[j];
        }
    }
}

void testRadixSort() {
    printf("\n-----radixSort-----begin\n");
    int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
    int len = (int) sizeof(arr) / sizeof(*arr);
    radixSort(arr, len, 2);
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n-----radixSort-----end\n");
}

桶排序

#include <stdlib.h>
#include <printf.h>

typedef struct BucketNode {
    int data;
    struct BucketNode *next;
} BucketNode;

struct BucketNode *creatBucketNode(int value) {
    BucketNode *node = (BucketNode *) malloc(sizeof(BucketNode));
    node->next = NULL;
    node->data = value;
    return node;
}

/**
 * 数组+链表的方式:存放桶数据
 * @param arr
 * @param length
 * @param bucketCounts 桶的数量
 */
void bucketSort(int arr[], int length, int bucketCounts) {
    if (length == 0) {
        return;
    }
    int min = arr[0];
    int max = arr[0];

    for (int i = 1; i < length; i++) {
        if (arr[i] < min) {
            min = arr[i];
        } else if (arr[i] > max) {
            max = arr[i];
        }
    }

    // 桶的容量
    int bucketSize = (max - min) / bucketCounts + 1;
    BucketNode **buckets = (BucketNode **) malloc(sizeof(BucketNode *) * bucketCounts);

    for (int i = 0; i < bucketCounts; i++) {
        // 创建头结点
        buckets[i] = creatBucketNode(-1);
    }

    for (int i = 0; i < length; i++) {
        int index = (arr[i] - min) / bucketSize;
        BucketNode *node = buckets[index];
        BucketNode *p = node;
        while (p->next) {
            // 遍历链表,找到要插入的位置
            if (p->next->data >= arr[i]) {
                break;
            }
            p = p->next;
        }
        // 对应桶中插入arr[i]的结点
        BucketNode *insertNode = creatBucketNode(arr[i]);
        BucketNode *temp = p->next;
        p->next = insertNode;
        insertNode->next = temp;
    }

    int i = 0;
    for (int j = 0; j < bucketCounts; ++j) {
        BucketNode *p = buckets[j];
        while (p->next) {
            arr[i++] = p->next->data;
            p = p->next;
        }
    }
}

void testBucketSort() {
    printf("\n-----bucketSort-----begin\n");
    int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
    int len = (int) sizeof(arr) / sizeof(*arr);
    bucketSort(arr, len, 4);
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n-----bucketSort-----end\n");
}

计数排序

#include <stdio.h>
#include <stdlib.h>

void countingSort(int arr[], int length, int max) {
    int * bucket = (int *) malloc(sizeof(int) * max);
    int i, j;
    for (i = 0; i < max; i++) {
        // 一开始都是0
        bucket[i] = 0;
    }
    for (i = 0; i < length; i++) {
        int index = arr[i];
        // 用value作为bucket的index
        bucket[index] = bucket[index] + 1;
    }

    for (i = 0, j = 0; i < max; i++) {
        int size = bucket[i];
        while (size > 0) {
            arr[j++] = i;
            size--;
        }
    }
}


void testCountingSort() {
    printf("\n-----countingSort-----begin\n");
    int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
    int len = (int) sizeof(arr) / sizeof(*arr);
    countingSort(arr, len, 100);
    int i;
    for (i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n-----countingSort-----end\n");
}

线性表

数组

#include <printf.h>
#include <stdlib.h>

void testListArray() {
    printf("\n-----数组-----begin\n");
    int array1[] = {1, 2, 3, 4, 5};

    // 动态数组创建
    int *array2 = (int *) malloc(sizeof(int) * 10);
    array2[1] = 10;

    // 二维数组动态创建
    int **array3 = (int **) malloc(sizeof(int *) * 10);
    for (int i = 0; i < 10; ++i) {
        array3[i] = (int *) malloc(sizeof(int) * 5);
    }
    array3[1][4] = 1;
    printf("array[1]=%d  array3[1][4]=%d", array1[1], array3[1][4]);
    printf("\n-----数组-----end\n");
}

链表

#include <printf.h>
#include <stdlib.h>

// 单链表
typedef struct ListLink {
    char data;
    struct ListLink *next;
} ListLink;

// 双向链表
typedef struct ListDoubleLink {
    char data;
    struct ListDoubleLink *next;
    struct ListDoubleLink *pre;
} ListDoubleLink;

struct ListLink *creatListLinkNode(char value) {
    ListLink *node = (ListLink *) malloc(sizeof(ListLink));
    node->next = NULL;
    node->data = value;
    return node;
}

void testListLink() {
    printf("\n-----链表-----begin\n");
    ListLink *head = creatListLinkNode('h');
    char c = 'a';
    // 带头结点的单链表:头结点head的next指向a
    // 不带头结点单链表:第一个结点就是a,而不是head
    // 带头结点的循环单链表:尾部rear,rear->next=head rear->next->next=a
    // 不带头结点循环单链表:尾部rear,rear->next=a
    ListLink *p = head;
    while (c < 'e') {
        p->next = creatListLinkNode(c);
        p = p->next;
        c++;
    }

    p = head->next;
    // 遍历单链表
    while (p) {
        printf("%c ", p->data);
        p = p->next;
    }

    // 删除c
    p = head;
    while (p->next) {
        if (p->next->data == 'c') {
            break;
        }
        p = p->next;
    }
    if (p->next) {
        p->next = p->next->next;
    }

    p = head->next;
    printf("\n删除c后的单链表:");
    while (p) {
        printf("%c ", p->data);
        p = p->next;
    }

    printf("\n-----链表-----begin\n");
}

#include <stdlib.h>
#include <printf.h>

void testListStack() {
    printf("\n-----栈-----begin\n");
    // 动态数组做栈
    char *stack = (char *) malloc(sizeof(char) * 10);
    int i = 0;
    char c = 'a';
    while (c < 'e') {
        stack[i++] = c;
        c++;
    }

    printf("出栈:");
    while (i > 0) {
        // i=0表示栈为空
        printf("%c ", stack[--i]);
    }

    printf("\n-----栈-----end\n");
}

队列

#include <stdlib.h>
#include <printf.h>

void testListQueue() {
    printf("\n-----队列-----begin\n");
    // 动态数组做队列:无头结点的队列
    char *queue = (char *) malloc(sizeof(char) * 10);
    int rear = 0, front = 0;
    char c = 'a';
    while (c < 'e') {
        queue[rear++] = c++;
    }

    printf("出队:");
    while (front < rear) {
        printf("%c ", queue[front++]);
    }

    printf("\n-----队列-----end\n");
}

查找

顺序查找

#include <printf.h>

int linearFind(int arr[], int length, int value) {
    for (int i = 0; i < length; i++) {
        if (arr[i] == value) {
            return i;
        }
    }
    return -1;
}

void testFindLinear() {
    printf("\n-----find-linear-----begin\n");
    int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
    int len = (int) sizeof(arr) / sizeof(*arr);
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\nvalue %d index:%d", arr[3], linearFind(arr, len, arr[3]));
    printf("\n-----find-linear-----end\n");
}

二分查找

#include <printf.h>

int binaryFind(int arr[], int length, int value) {
    int low = 0, high = length - 1, mid;
    if (arr[low] > value || arr[high] < value) {
        // 直接返回-1
        return -1;
    }

    while (low <= high && value >= arr[low] && value <= arr[high]) {
        mid = low + (high - low) / 2;
        if (value == arr[mid]) {
            return mid;
        }
        if (arr[mid] > value) {
            high = mid - 1;
        } else {
            low = mid + 1;
        }
    }

    return -1;
}

void _bubbleSort(int arr[], int len) {
    int i, j, temp;
    int flag;
    for (i = 0; i < len - 1; i++) {
        flag = 0;
        for (j = 0; j < len - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                flag = 1;
            }
        }
        if (flag == 0) {
            // 说明没有需要交换的数,说明所有的数已排序
            return;
        }
    }
}

void testFindBinary() {
    printf("\n-----find-binary-----begin\n");
    int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
    int len = (int) sizeof(arr) / sizeof(*arr);
    // 二分查找 要求已排序
    _bubbleSort(arr, len);
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\nvalue %d index:%d", arr[3], binaryFind(arr, len, arr[3]));
    printf("\nvalue %d index:%d", 21, binaryFind(arr, len, 21));
    printf("\n-----find-binary-----end\n");
}

哈希查找

#include <stdlib.h>
#include <printf.h>

#define HASH_SIZE 8
typedef struct HashNode {
    // 数组下标,当然也可以再存储value
    int index;
    int value;
    struct HashNode *next;
} HashNode;

struct HashNode *creatHashNode(int index) {
    HashNode *node = (HashNode *) malloc(sizeof(HashNode));
    node->next = NULL;
    node->index = index;
    return node;
}

struct HashNode *creatHashNode2(int index, int value) {
    HashNode *node = (HashNode *) malloc(sizeof(HashNode));
    node->index = index;
    node->value = value;
    return node;
}

int hashCode(int v) {
    return v % 8;
}

HashNode **createHashLinkHead(int arr[], int length) {
    HashNode **head = (HashNode **) malloc(sizeof(HashNode *) * HASH_SIZE);
    for (int i = 0; i < HASH_SIZE; i++) {
        // 带头结点的哈希表
//        head[i] = (HashNode *) malloc(sizeof(HashNode));
        head[i] = creatHashNode(-1);
    }
    int hashKey;
    HashNode *node;
    // 链地址法建表
    for (int i = 0; i < length; i++) {
        hashKey = hashCode(arr[i]);
        node = head[hashKey];
        while (node->next) {
            // 找到最后一个结点
            node = node->next;
        }
        // 插入到链表最后一个结点
        node->next = creatHashNode(i);
    }
    return head;
}

int findHashLink(HashNode **head, int arr[], int value) {
    HashNode *node = head[hashCode(value)]->next;
    while (node) {
        if (arr[node->index] == value) {
            return node->index;
        }
        node = node->next;
    }
    return -1;
}

HashNode **createLinearHashTable(int arr[], int length) {
    // 这里设置size为16:保证能放下待查找数组每个数
    HashNode **table = (HashNode **) malloc(sizeof(HashNode *) * HASH_SIZE * 2);
    for (int i = 0; i < HASH_SIZE * 2; i++) {
        // 暂定-1为空
        table[i] = creatHashNode2(-1, -1);
    }

    int index;
    for (int i = 0; i < length; i++) {
        index = hashCode(arr[i]);
        while (table[index]->value != -1) {
            // 不空,则找到下一个非空位置index
            index = (index + 1) % (HASH_SIZE * 2);
        }
        // 插入到哈希表中
        table[index] = creatHashNode2(i, arr[i]);
    }
    return table;
}

int findHashLinear(HashNode **table, int value) {
    int index = hashCode(value);
    int i = 0;
    while (table[index]->index != -1 && i < HASH_SIZE * 2) {
        if (table[index]->value == value) {
            return table[index]->index;
        }
        // 找不到value看下一个位置
        index = (index + 1) % (HASH_SIZE * 2);
        // i=16时:说明整个哈希表都找了一遍,没发现value
        i++;
    }
    // index对应哈希表为空
    return -1;
}

void testFindHash() {
    int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
    int len = (int) sizeof(arr) / sizeof(*arr);
    printf("\n-----链地址法-----begin\n");
    HashNode **linkHead = createHashLinkHead(arr, len);
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\nvalue %d index:%d", arr[3], findHashLink(linkHead, arr, arr[3]));
    printf("\nvalue %d index:%d", 21, findHashLink(linkHead, arr, 21));
    printf("\n-----链地址法-----end\n");
    printf("\n-----线性在探测法-----begin\n");
    HashNode **linearTable = createLinearHashTable(arr, len);
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\nvalue %d index:%d", arr[3], findHashLinear(linearTable, arr[3]));
    printf("\nvalue %d index:%d", 21, findHashLinear(linearTable, 21));

    printf("\n-----线性在探测法-----end\n");
}

插值查找

#include <printf.h>

int interpolationFind(int arr[], int length, int value) {
    int low = 0, high = length - 1, mid;
    if (arr[low] > value || arr[high] < value) {
        // 直接返回-1
        return -1;
    }

    while (low <= high && value >= arr[low] && value <= arr[high]) {
        // 计算mid的方式:是唯一和二分查找的区别
        int mid = low + (high - low) * (value - arr[low]) / (arr[high] - arr[low]);
        if (value == arr[mid]) {
            return mid;
        }
        if (arr[mid] > value) {
            high = mid - 1;
        } else {
            low = mid + 1;
        }
    }

    return -1;
}

void __bubbleSort(int arr[], int len) {
    int i, j, temp;
    int flag;
    for (i = 0; i < len - 1; i++) {
        flag = 0;
        for (j = 0; j < len - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                flag = 1;
            }
        }
        if (flag == 0) {
            // 说明没有需要交换的数,说明所有的数已排序
            return;
        }
    }
}

void testFindInterpolation() {
    printf("\n-----find-interpolation-----begin\n");
    int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
    int len = (int) sizeof(arr) / sizeof(*arr);
    // 插值查找 要求已排序
    __bubbleSort(arr, len);
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\nvalue %d index:%d", arr[3], interpolationFind(arr, len, arr[3]));
    printf("\nvalue %d index:%d", 21, interpolationFind(arr, len, 21));
    printf("\n-----find-interpolation-----end\n");
}

KMP算法

#include <stdlib.h>
#include <printf.h>
#include <string.h>

/**
 * 
 * @param pattern 模式串
 * @param len 
 * @return next数组
 */
int *getNext(const char pattern[], int len) {
    int *next = (int *) malloc(sizeof(int) * len);
    next[0] = -1;
    next[1] = 0;
    for (int i = 2; i < len; i++) {
        int last = next[i - 1];
        if (pattern[i - 1] == pattern[last]) {
            next[i] = last + 1;
        } else {
            next[i] = 0;
        }
    }
    return next;
}

/**
 *
 * @param str 主串
 * @param pattern 模式串
 * @return {number} 匹配成功时,返回模式串在主串的位置;失败返回-1
 */
int kmp(char str[], char pattern[]) {
    int len1 = strlen(str);
    int len2 = strlen(pattern);
    int *next = getNext(pattern, len2);

    int j = 0;
    for (int i = 0; i < len1; i++) {
        while (j > 0 && str[i] != pattern[j]) {
            j = next[j];
        }
        if (str[i] == pattern[j]) {
            j++;
        }
        if (j == len2) {
            return i - len2 + 1;
        }
    }
    return -1;
}

void testKmp() {
    printf("\n-----kmp-----begin\n");
    char str[] = "abcabcabacba";
    char pattern1[] = "abcabb";
    char pattern2[] = "bcaba";

    printf("主串:%s, 模式串:%s, 匹配结果:%d\n", str, pattern1, kmp(str, pattern1));
    printf("主串:%s, 模式串:%s, 匹配结果:%d\n", str, pattern2, kmp(str, pattern2));

    printf("\n-----kmp-----begin\n");
}

二叉树

各种遍历递归+非递归实现

#include <stdlib.h>
#include <printf.h>

typedef struct TreeNode {
    int value;
    char data;
    struct TreeNode *left;
    struct TreeNode *right;
} TreeNode;

struct TreeNode *creatTree(char value) {
    TreeNode *treeNode = (TreeNode *) malloc(sizeof(TreeNode));
    treeNode->left = NULL;
    treeNode->right = NULL;
    treeNode->data = value;
    return treeNode;
}

// 先序遍历递归实现
void preTreeOrder1(TreeNode *root) {
    if (!root) {
        return;
    }
    printf("%c ", root->data);
    preTreeOrder1(root->left);
    preTreeOrder1(root->right);
}

// 先序遍历非递归实现
void preTreeOrder2(TreeNode *root) {
    if (!root) {
        return;
    }
    struct TreeNode **stack = (struct TreeNode **) malloc(sizeof(struct TreeNode *) * 10);
    int i = 0;
    stack[i++] = root;
    TreeNode *node;
    while (i > 0) {
        // 栈非空
        node = stack[--i];
        printf("%c ", node->data);
        if (node->right) {
            stack[i++] = node->right;
        }
        if (node->left) {
            stack[i++] = node->left;
        }
    }
}

// 中序遍历递归实现
void midTreeOrder1(TreeNode *root) {
    if (!root) {
        return;
    }
    midTreeOrder1(root->left);
    printf("%c ", root->data);
    midTreeOrder1(root->right);
}

// 中序遍历非递归实现
void midTreeOrder2(TreeNode *root) {
    if (!root) {
        return;
    }
    struct TreeNode **stack = (struct TreeNode **) malloc(sizeof(struct TreeNode *) * 10);
    int i = 0;
    TreeNode *node = root;
    while (node || i > 0) {
        while (node) {
            // 有左节点就进栈
            stack[i++] = node;
            node = node->left;
        }
        if (i > 0) {
            // 没有左节点就是中间节点、所以访问
            node = stack[--i];
            printf("%c ", node->data);
            // 看是否有右节点
            node = node->right;
        }
    }
}

// 后序遍历递归实现
void lastTreeOrder1(TreeNode *root) {
    if (!root) {
        return;
    }
    midTreeOrder1(root->left);
    midTreeOrder1(root->right);
    printf("%c ", root->data);
}

// 后序遍历非递归实现
void lastTreeOrder2(TreeNode *root) {
    if (!root) {
        return;
    }
    struct TreeNode **stack = (struct TreeNode **) malloc(sizeof(struct TreeNode *) * 10);
    int i = 0;
    TreeNode *node = root;
    // 记录上一个访问的节点
    TreeNode *preNode;
    while (node || i > 0) {
        while (node) {
            // 有左节点就进栈
            stack[i++] = node;
            node = node->left;
        }

        if (i > 0) {
            // 取出栈顶,但是不出栈
            node = stack[i - 1];
            if (!node->right || node->right == preNode) {
                // 右节点为空、或者右节点已访问
                preNode = stack[--i];
                printf("%c ", preNode->data);
                node = NULL;
            } else {
                node = node->right;
            }
        }
    }
}

void levelOrder(struct TreeNode *root) {
    if (root == NULL) {
        return;
    }
    // 动态数组做队列
    struct TreeNode **queue = (struct TreeNode **) malloc(sizeof(struct TreeNode *) * 10);
    int rear = 0, front = 0;
    queue[rear++] = root;
    struct TreeNode *temp;
    while (rear > front) {
        temp = queue[front++];
        printf("%c", temp->data);
        if (temp->left) {
            queue[rear++] = temp->left;
        }
        if (temp->right) {
            queue[rear++] = temp->right;
        }
    }
}

/**
 *
 * @param root
 * @return
 */
int getTreeWpl(struct TreeNode *root) {
    if (root == NULL) {
        return 0;
    }
    // 动态数组做队列
    struct TreeNode **queue = (struct TreeNode **) malloc(sizeof(struct TreeNode *) * 10);
    int rear = 0, front = 0;
    queue[rear++] = root;
    struct TreeNode *temp;
    int wpl = 0;
    while (rear > front) {
        temp = queue[front++];
        if (temp->left || temp->right) {
            // 计算非叶结点的权值之和
            wpl += temp->value;
        }
        if (temp->left) {
            queue[rear++] = temp->left;
        }
        if (temp->right) {
            queue[rear++] = temp->right;
        }
    }
    return wpl;
}

void testTreeOrder() {
    TreeNode *treeNode1 = creatTree('a');
    TreeNode *treeNode2 = creatTree('b');
    TreeNode *treeNode3 = creatTree('c');
    TreeNode *treeNode4 = creatTree('d');
    TreeNode *treeNode5 = creatTree('e');
    treeNode1->left = treeNode2;
    treeNode1->right = treeNode3;
    treeNode3->left = treeNode4;
    treeNode3->right = treeNode5;

    // 哈夫曼树测试数据 wpl=(4+3)*2+6*1=20 or wpl=7+13=20
    treeNode4->value = 4;
    treeNode5->value = 3;
    treeNode3->value = 7;
    treeNode2->value = 6;
    treeNode1->value = 13;


    printf("\n-----先序遍历递归-----begin\n");
    preTreeOrder1(treeNode1);
    printf("\n-----先序遍历递归-----end\n");
    printf("\n-----先序遍历非递归-----begin\n");
    preTreeOrder2(treeNode1);
    printf("\n-----先序遍历非递归-----end\n");

    printf("\n-----中序遍历递归-----begin\n");
    midTreeOrder1(treeNode1);
    printf("\n-----中序遍历递归-----end\n");
    printf("\n-----中序遍历非递归-----begin\n");
    midTreeOrder2(treeNode1);
    printf("\n-----中序遍历非递归-----end\n");

    printf("\n-----后序遍历递归-----begin\n");
    lastTreeOrder1(treeNode1);
    printf("\n-----后序遍历递归-----end\n");
    printf("\n-----后序遍历非递归-----begin\n");
    lastTreeOrder2(treeNode1);
    printf("\n-----后序遍历非递归-----end\n");

    printf("\n-----层序遍历-----begin\n");
    levelOrder(treeNode1);
    printf("\n-----层序遍历-----end\n");

    printf("wpl=%d\n",getTreeWpl(treeNode1));
}

数据结构定义:邻接表、邻接矩阵

#include <stdlib.h>

#ifndef STRUCTURE_SOURCE_GRAPH_STRUCTURE
#define STRUCTURE_SOURCE_GRAPH_STRUCTURE
/**
 * 邻接表表结点,不带头结点链表
 */
typedef struct ArcNode {
    int index; // 顶点序号,从0开始
    char value; // 顶点值
    int val;
    struct ArcNode *next; //邻接链表
} ArcNode;

//邻接表
typedef struct {
    ArcNode **adjList; // 邻接表数组
    int n, e;//顶点总数 边数
} AdjGraph;


#define VERTEX_SIZE 5
typedef struct GraphVertex {
    int index; // 顶点序号,从0开始
    char value; // 顶点值
} GraphVertex;

typedef struct {
    GraphVertex *vertex[VERTEX_SIZE];
    int matrix[VERTEX_SIZE][VERTEX_SIZE];
    int vertexNum;
    int arcNum;
} MatrixGraph;

struct ArcNode *creatArcNode(char value, int index, const int adjArr[], int adjSize);

AdjGraph *createAdjGraph();

int getRandomRestPoint(AdjGraph *graph, const int *visited);


struct GraphVertex *creatVertex(char value, int index);

// 无向图
MatrixGraph *createMatrixGraph();

// 生成树
MatrixGraph *createSpanningGraph();

#endif
#include "graph-structure.h"

struct ArcNode *creatArcNode(char value, int index, const int adjArr[], int adjSize) {
    ArcNode *node = (ArcNode *) malloc(sizeof(ArcNode));
    node->value = value;
    node->index = index;
    ArcNode *temp = node, *p;
    for (int i = 0; i < adjSize; ++i) {
        p = (ArcNode *) malloc(sizeof(ArcNode));
        p->index = adjArr[i];
        temp->next = p;
        temp = p;
    }
    temp->next = NULL;
    return node;
}

AdjGraph *createAdjGraph() {
    struct ArcNode **array = (struct ArcNode **) malloc(sizeof(struct ArcNode *) * 7);
    int adj0[] = {1, 2};
    int adj1[] = {0, 3, 4};
    int adj2[] = {0};
    int adj3[] = {1};
    int adj4[] = {1};
    int adj5[] = {6};
    int adj6[] = {5};
    ArcNode *node0 = creatArcNode('A', 0, adj0, 2);
    ArcNode *node1 = creatArcNode('B', 1, adj1, 3);
    ArcNode *node2 = creatArcNode('C', 2, adj2, 1);
    ArcNode *node3 = creatArcNode('D', 3, adj3, 1);
    ArcNode *node4 = creatArcNode('E', 4, adj4, 1);
    ArcNode *node5 = creatArcNode('F', 5, adj5, 1);
    ArcNode *node6 = creatArcNode('G', 6, adj6, 1);
    array[0] = node0;
    array[1] = node1;
    array[2] = node2;
    array[3] = node3;
    array[4] = node4;
    array[5] = node5;
    array[6] = node6;
    AdjGraph *graph = (AdjGraph *) malloc(sizeof(AdjGraph));
    graph->n = 7;
    graph->e = (2 + 3 + 1 + 1 + 1 + 1 + 1) / 2;
    graph->adjList = array;
    return graph;
}

// 随机获取一个未访问顶点
int getRandomRestPoint(AdjGraph *graph, const int *visited) {
    for (int i = 0; i < graph->n; i++) {
        if (visited[i] == 0) {
            return i;
        }
    }
    return -1;
}

struct GraphVertex *creatVertex(char value, int index) {
    GraphVertex *vertex = (GraphVertex *) malloc(sizeof(GraphVertex));
    vertex->index = index;
    vertex->value = value;
    return vertex;
}

MatrixGraph *createMatrixGraph() {
    MatrixGraph *graph = (MatrixGraph *) malloc(sizeof(MatrixGraph));
    char a = 'A';
    for (int i = 0; i < VERTEX_SIZE; i++) {
        graph->vertex[i] = creatVertex(a++, i);
    }
    int matrix[VERTEX_SIZE][VERTEX_SIZE] = {
            {0, 5, 4, 0, 0},
            {5, 0, 0, 2, 7},
            {4, 0, 0, 0, 0},
            {0, 2, 0, 0, 1},
            {0, 6, 0, 1, 0},
    };

    int arcSize = 0;
    for (int i = 0; i < VERTEX_SIZE; i++) {
        for (int j = i; j < VERTEX_SIZE; j++) {
            if (i == j) {
                graph->matrix[i][j] = 0;
            } else {
                if (matrix[i][j] > 0) {
                    arcSize++;
                }
                graph->matrix[i][j] = matrix[i][j];
                graph->matrix[j][i] = matrix[i][j];
            }
        }
    }
    graph->arcNum = arcSize;
    graph->vertexNum = VERTEX_SIZE;
    return graph;
}

MatrixGraph *createSpanningGraph() {
    MatrixGraph *graph = (MatrixGraph *) malloc(sizeof(MatrixGraph));
    char a = 'A';
    for (int i = 0; i < VERTEX_SIZE; i++) {
        graph->vertex[i] = creatVertex(a++, i);
    }
    int matrix[VERTEX_SIZE][VERTEX_SIZE] = {
            {0,  7,  14, 9, 0},
            {7,  0,  17, 0, 5},
            {14, 17, 0,  4, 15},
            {9,  0,  4,  0, 0},
            {0,  5,  15, 0, 0},
    };

    int arcSize = 0;
    for (int i = 0; i < VERTEX_SIZE; i++) {
        for (int j = i; j < VERTEX_SIZE; j++) {
            if (i == j) {
                graph->matrix[i][j] = 0;
            } else {
                if (matrix[i][j] > 0) {
                    arcSize++;
                }
                graph->matrix[i][j] = matrix[i][j];
                graph->matrix[j][i] = matrix[i][j];
            }
        }
    }
    graph->arcNum = arcSize;
    graph->vertexNum = VERTEX_SIZE;
    return graph;
}

DFS

#include <printf.h>
#include "graph-structure.h"

/**
 * 邻接矩阵的dfs
 * @param graph 邻接矩阵
 * @param i 开始顶点
 */
void dfs(AdjGraph *graph, int i) {
    // 记录已访问顶点:0表示未访问,1表示已访问
    int *visited = (int *) malloc(sizeof(int) * graph->n);
    for (int j = 0; j < graph->n; j++) {
        visited[j] = 0;
    }

    // 待访问顶点栈
    int *stack = (int *) malloc(sizeof(int) * graph->n);
    int index = 0;
    stack[index++] = i;

    // 已访问顶点个数
    int size = 0;
    ArcNode *node;
    while (size < graph->n) {
        while (index > 0) {
            int currentIndex = stack[--index];
            node = graph->adjList[currentIndex];
            printf("%c ", node->value);
            // 访问结点后:更新visited、size
            visited[currentIndex] = 1;
            size++;
            if (size == graph->n) {
                return;
            }
            node = node->next;
            while (node) {
                // 遍历node相邻顶点,找到未访问的加入栈
                if (visited[node->index] == 0) {
                    stack[index++] = node->index;
                }
                node = node->next;
            }
        }
        if (size < graph->n) {
            // 如果栈为空,但是size<n;说明图G不是连通图,需要在未遍历顶点中随机再找一个顶点进行dfs
            stack[index++] = getRandomRestPoint(graph, visited);
        }
    }
}

void testDfs() {
    printf("\n-----dfs-----begin\n");
    AdjGraph *graph = createAdjGraph();
    printf("起点:%c dfs结果为:", graph->adjList[3]->value);
    dfs(graph, 3);
    printf("\n起点:%c dfs结果为:", graph->adjList[5]->value);
    dfs(graph, 5);
    printf("\n-----dfs-----end\n");
}

BFS

#include <printf.h>
#include "graph-structure.h"

/**
 * 邻接矩阵的dfs
 * @param graph 邻接矩阵
 * @param i 开始顶点
 */
void bfs(AdjGraph *graph, int i) {
    // 记录已访问顶点:0表示未访问,1表示已访问
    int *visited = (int *) malloc(sizeof(int) * graph->n);
    for (int j = 0; j < graph->n; j++) {
        visited[j] = 0;
    }

    // 待访问顶点队列
    int *queue = (int *) malloc(sizeof(int) * graph->n);
    int rear = 0, front = 0;
    queue[rear++] = i;

    int size = 0;
    ArcNode *node;
    while (size < graph->n) {
        while (front < rear) {
            int currentIndex = queue[front++];
            node = graph->adjList[currentIndex];
            printf("%c ", node->value);
            // 访问结点后:更新visited、size
            visited[currentIndex] = 1;
            size++;
            node = node->next;
            while (node) {
                // 遍历node相邻顶点,找到未访问的加入栈
                if (visited[node->index] == 0) {
                    queue[rear++] = node->index;
                }
                node = node->next;
            }
        }
        if (size < graph->n) {
            // 如果队列为空,但是size<n;说明图G不是连通图,需要在未遍历顶点中随机再找一个顶点进行bfs
            queue[rear++] = getRandomRestPoint(graph, visited);
        }
    }
}

void testBfs() {
    printf("\n-----bfs-----begin\n");
    AdjGraph *graph = createAdjGraph();
    printf("起点:%c bfs结果为:", graph->adjList[3]->value);
    bfs(graph, 3);
    printf("\n起点:%c bfs结果为:", graph->adjList[5]->value);
    bfs(graph, 5);
    printf("\n-----dfs-----end\n");
}

迪杰斯特拉算法

#include <printf.h>
#include "graph-structure.h"

// 无限大
#define INF 100

/**
 *
 * @param graph 邻接矩阵
 * @param i 起始点
 * @param j 终点
 * @return i到j的最短距离
 */
int dijkstra(MatrixGraph *graph, const int i, const int j) {
    int n = graph->vertexNum;
    // 记录最短距离
    int *minDistance = (int *) malloc(sizeof(int) * n);
    for (int k = 0; k < n; k++) {
        // 一开始除了i都是无穷大
        minDistance[k] = k == i ? 0 : INF;
    }

    // 记录已访问顶点:0表示未访问,1表示已访问
    int *visited = (int *) malloc(sizeof(int) * n);
    for (int k = 0; k < n; k++) {
        visited[k] = 0;
    }
    visited[i] = 1;

    int size = 1;
    int current = i;
    int minIndex, minDis;
    while (size < n) {
        for (int k = 0; k < n; k++) {
            if (visited[k] == 0 && graph->matrix[current][k] > 0) {
                // 获取当前current顶点未访问顶点
                int dis = minDistance[current] + graph->matrix[current][k];
                if (dis < minDistance[k]) {
                    // 如果(i到current+current到k)小于minDis:更新minDis
                    minDistance[k] = dis;
                }
            }
        }

        minIndex = -1;
        minDis = INF;
        for (int k = 0; k < n; k++) {
            // 获取当前current顶点未访问顶点, 距离最小的点
            if (visited[k] == 0 && minDistance[k] < minDis) {
                minDis = minDistance[k];
                minIndex = k;
            }
        }
        if (minIndex == j) {
            // 如果是目标顶点,直接返回dis
            return minDis;
        }
        if (minIndex == -1) {
            // 说明没有相邻顶点了,直接返回无穷大
            return INF;
        }
        visited[minIndex] = 1;
        current = minIndex;
        size++;
    }
}

void testDijkstra() {
    printf("\n-----dijkstra-----begin\n");
    MatrixGraph *graph = createMatrixGraph();
    int i = 0;
    int j = 4;
    printf("顶点%c到顶点%c最短距离:%d", graph->vertex[i]->value, graph->vertex[j]->value,
           dijkstra(graph, i, j));
    printf("\n-----dijkstra-----end\n");
}

Floyd算法

// 无限大:表示没有连接路径
#include <printf.h>
#include "graph-structure.h"

#define INF 100

/**
 * 邻接矩阵的floyd算法 复杂度O(n³)
 * @param graph
 * @return
 */
int **floyd(MatrixGraph *graph) {
    int n = graph->vertexNum;
    int **matrix = (int **) malloc(sizeof(int *) * n);
    for (int i = 0; i < n; i++) {
        matrix[i] = (int *) malloc(sizeof(int) * n);
    }

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (graph->matrix[i][j] == 0) {
                matrix[i][j] = INF;
            } else {
                matrix[i][j] = graph->matrix[i][j];
            }
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            for (int k = 0; k < n; k++) {
                if (matrix[i][k] == INF || matrix[k][j] == INF) {
                    continue;
                }
                if (matrix[i][k] + matrix[k][j] < matrix[i][j]) {
                    matrix[i][j] = matrix[i][k] + matrix[k][j];
                }
            }
        }
    }
    return matrix;
}

void testFloyd() {
    printf("\n-----floyd-----begin\n");
    MatrixGraph *graph = createMatrixGraph();
    int i = 0;
    int j = 4;
    int **matrix = floyd(graph);
    printf("顶点%c到顶点%c最短距离:%d\n", graph->vertex[i]->value, graph->vertex[j]->value,
           matrix[i][j]);
    printf("顶点%c到顶点%c最短距离:%d", graph->vertex[1]->value, graph->vertex[4]->value,
           matrix[1][4]);
    printf("\n-----floyd-----end\n");
}

拓扑排序

#include <printf.h>
#include "graph-structure.h"

// 创建一个有向无环图
MatrixGraph *createDagGraph() {
    MatrixGraph *graph = (MatrixGraph *) malloc(sizeof(MatrixGraph));
    char a = 'A';
    for (int i = 0; i < VERTEX_SIZE; i++) {
        graph->vertex[i] = creatVertex(a++, i);
    }
    int matrix[VERTEX_SIZE][VERTEX_SIZE] = {
            {0, 1, 1, 1, 0},
            {0, 0, 0, 0, 0},
            {0, 1, 0, 0, 1},
            {0, 0, 0, 0, 1},
            {0, 0, 0, 0, 0},
    };

    for (int i = 0; i < VERTEX_SIZE; i++) {
        for (int j = 0; j < VERTEX_SIZE; j++) {
            graph->matrix[i][j] = matrix[i][j];
        }
    }
    graph->vertexNum = VERTEX_SIZE;
    return graph;
}

// 剩余顶点中找到入度为0的点;-1表示没有入度为0的点
int getIn0(MatrixGraph *graph, const int *visited) {
    for (int i = 0; i < graph->vertexNum; i++) {
        if (visited[i] == 1) {
            continue;
        }
        int degree = 0;
        for (int j = 0; j < graph->vertexNum; j++) {
            if (visited[j] == 1) {
                continue;
            }
            degree += graph->matrix[j][i];
            if (degree > 0) {
                break;
            }
        }
        if (degree == 0) {
            return i;
        }
    }
    return -1;
}

/**
 * 拓扑排序:输出排序列表
 * @param graph
 * @return 1表示是有向无环图,支持拓扑排序,0表示不是有向无环图
 */
int dagSort(MatrixGraph *graph) {
    int n = graph->vertexNum;

    // 记录已访问顶点:0表示未访问,1表示已访问
    int *visited = (int *) malloc(sizeof(int) * n);
    for (int i = 0; i < n; i++) {
        visited[i] = 0;
    }

    int size = 0;
    printf("拓扑排序:");
    while (size < graph->vertexNum) {
        int i = getIn0(graph, visited);
        if (i == -1) {
            return -1;
        }
        printf("%c ", graph->vertex[i]->value);
        visited[i] = 1;
        size++;
    }
    return 1;
}

void testDagSort() {
    printf("\n-----拓扑排序-----begin\n");
    MatrixGraph *graph = createDagGraph();
    int res = dagSort(graph);
    printf("   有向无环图:%d", res);
    printf("\n-----拓扑排序-----end\n");
}

Prim算法

#include <printf.h>
#include "graph-structure.h"

#define INF 100

int prim(MatrixGraph *graph) {
    int n = graph->vertexNum;

    // 记录已访问顶点:0表示未访问,1表示已访问(已固定的顶点)
    int *visited = (int *) malloc(sizeof(int) * n);
    // 记录每个顶点加入生成树T时在树中的父顶点:用于记录增加的边,如果只是计算最小值 可以不要parent
    int *parents = (int *) malloc(sizeof(int) * n);
    // 记录每个顶点已查询相邻边的最小值,初始为INF
    int *weights = (int *) malloc(sizeof(int) * n);

    for (int i = 0; i < n; i++) {
        visited[i] = 0;
        parents[i] = -1;
        weights[i] = INF;
    }

    // 加入第一个顶点
    int current = 0;
    parents[current] = -1;
    weights[current] = 0;
    visited[current] = 1;

    int ast = 0;
    int size = 1;
    int dis, minDis, minIndex;
    while (size < n) {
        for (int i = 0; i < n; i++) {
            dis = graph->matrix[current][i];
            if (visited[i] == 1 || dis == 0) {
                // 找相邻且没被访问的
                continue;
            }
            if (dis < weights[i]) {
                // 如果dis较小 更新weights和parent
                weights[i] = dis;
                parents[i] = current;
            }
        }

        // weights中最小的一个顶点固定
        minDis = INF;
        minIndex = -1;
        for (int i = 0; i < n; i++) {
            if (visited[i] == 1 || weights[i] == INF) {
                continue;
            }
            if (weights[i] < minDis) {
                minDis = weights[i];
                minIndex = i;
            }
        }
        if (minIndex != -1) {
            // 更新current,接下来看current相邻顶点
            current = minIndex;
            visited[minIndex] = 1;
            ast += minDis;
            size++;
        } else {
            return -1;
        }
    }
    for (int i = 1; i < n; i++) {
        int parent = parents[i];
        printf("%c%c ", graph->vertex[parent]->value, graph->vertex[i]->value);
    }
    return ast;
}

void testPrim() {
    printf("\n-----prim-----begin\n");
    MatrixGraph *graph = createSpanningGraph();
    int ast = prim(graph);
    printf("\nprim算法最小生成树大小为:%d", ast);
    printf("\n-----prim-----end\n");
}

Kruskal算法

#include <printf.h>
#include "graph-structure.h"

/**
 * 获取链表尾部结点
 * @param nextArray
 * @param start
 * @return {*}
 */
int findEndNode(const int *nextArray, int start) {
    while (nextArray[start] != -1) {
        start = nextArray[start];
    }
    return start;
}

typedef struct {
    int i;
    int j;
    int value;
} Edge;

// 对所有边排序
void bubbleEdgeSort(Edge **edgeList, int len) {
    int i, j;
    Edge *temp;
    int flag;
    for (i = 0; i < len - 1; i++) {
        flag = 0;
        for (j = 0; j < len - 1 - i; j++) {
            if (edgeList[j]->value > edgeList[j + 1]->value) {
                temp = edgeList[j];
                edgeList[j] = edgeList[j + 1];
                edgeList[j + 1] = temp;
                flag = 1;
            }
        }
        if (flag == 0) {
            // 说明没有需要交换的数,说明所有的数已排序
            return;
        }
    }
}

/**
 * kruskal算法
 * @param matrix
 * @return {*[{i,j,weight}]}
 */
int kruskal(MatrixGraph *graph) {
    int n = graph->vertexNum;
    Edge **edgeList = (struct Edge **) malloc(sizeof(Edge *) * graph->arcNum);
    int index = 0;
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            if (graph->matrix[i][j] == 0) {
                continue;
            }
            Edge *edge = (Edge *) malloc(sizeof(Edge));
            edge->i = i;
            edge->j = j;
            edge->value = graph->matrix[i][j];
            edgeList[index++] = edge;
        }
    }

    // 1. 对所有边排序
    bubbleEdgeSort(edgeList, graph->arcNum);
    // 2. 初始化next数组:用于判断是否有环
    int *nextArray = (int *) malloc(sizeof(int) * n);
    for (int i = 0; i < n; i++) {
        nextArray[i] = -1;
    }


    int nextIndex = 0;
    int size = 0;
    Edge *edge;
    int ast = 0;
    while (size < n - 1) {
        // 生成树为n-1条边
        edge = edgeList[nextIndex++];
        int u = findEndNode(nextArray, edge->i);
        int v = findEndNode(nextArray, edge->j);
        if (u != v) {
            // 表示无环
            printf("%c%c ", graph->vertex[edge->i]->value, graph->vertex[edge->j]->value);
            nextArray[u] = v;
            ast += edge->value;
            size++;
        }
    }
    return ast;
}

void testKruskal() {
    printf("\n-----kruskal-----begin\n");
    MatrixGraph *graph = createSpanningGraph();
    int res = kruskal(graph);
    printf("\nkruskal算法最小生成树大小为:%d", res);
    printf("\n-----kruskal-----end\n");

}