常见算法实现

数据结构 (Data Structure)

人总对有规律的数据处理更得心应手,同样计算机对有规律的数据处理也更加方便(计算机语言毕竟是人写的嘛)。为了处理不同的问题的数据,我们可以通过不同的数据结构来构建,然后通过与之对应的特殊算法来处理,从而高效解决问题。

链状数据结构 (Linked Data Structure)

数组 (Array)

无序数组 (Unordered Array)

实现代码

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

int *CreateArray(int maxLen, int *len)
{
    *len = 0;
    return (int *)malloc(maxLen * sizeof(int));
}

int InsertArray(int *array, int maxLen, int *len, int val)
{
    if (*len + 1 >= maxLen) {
        return -1;
    }
    array[*len] = val;
    *len = *len + 1;
    return 0;
}

int DeleteArray(int *array, int *len, int val)
{
    for (int i = 0; i < *len; i++) {
        if (array[i] == val) {
            for (int j = i; j + 1 < *len; j++) {
                array[j] = array[j + 1];
            }
            *len = *len - 1;
            return 0;
        }
    }

    return -1;
}

int UpdateArray(int *array, int len, int val, int updateVal)
{
    for (int i = 0; i < len; i++) {
        if (array[i] == val) {
            array[i] = updateVal;
            return 0;
        }
    }

    return -1;
}

int SeletcArray(int *array, int len, int val)
{
    for (int i = 0; i < len; i++) {
        if (array[i] == val) {
            return i;
        }
    }

    return -1;
}

int DestoryArray(int *array)
{
    free(array);
    return 0;
}

void PrintfArray(int *array, int len)
{
    printf("[");
    for (int i = 0; i < len; i++) {
        printf("%d", array[i]);
        if (i < len - 1) {
            printf(",");
        }
    }
    printf("]\r\n");
}

int main(void)
{
    int *array = NULL;
    int maxLen = 1000;
    int len = 0;

    array = CreateArray(maxLen, &len);
    InsertArray(array, maxLen, &len, 1);
    InsertArray(array, maxLen, &len, 2);
    InsertArray(array, maxLen, &len, 2);
    InsertArray(array, maxLen, &len, 3);
    InsertArray(array, maxLen, &len, 3);
    InsertArray(array, maxLen, &len, 4);
    InsertArray(array, maxLen, &len, 6);
    DeleteArray(array, &len, 3);
    DeleteArray(array, &len, 2);
    UpdateArray(array, len, 6, 5);
    printf("select=%d\r\n", SeletcArray(array, len, 5));
    PrintfArray(array, len);
    DestoryArray(array);
  
    return 0;
}

有序数组 (Ordered Array)

定义
数组为递增或递降存储。由于是有序的,则在增删改查的时候可以用二分法

实现代码

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

int *CreateArray(int maxLen, int *len)
{
    *len = 0;
    return (int *)malloc(maxLen * sizeof(int));
}

static int GetLocationFromArray(int *array, int len, int val)
{
    int location = -1;
    int l = 0, r = len - 1, m = (l + r) / 2;
    
    while (l <= r) {
        if (val < array[m]) {
            r = m - 1;
            m = (l + r) / 2;
        } else if (val > array[m]) {
            l = m + 1;
            m = (l + r) / 2;
        } else {
            location = m;
            break;
        }
    }
    
    return location;
}

int InsertArray(int *array, int maxLen, int *len, int val)
{
    if (*len + 1 >= maxLen) {
        return -1;
    }

    int end = *len;
    while (end - 1 >= 0 && val < array[end - 1]) {
        array[end] = array[end - 1];
        end--;
    }
    array[end] = val;
    *len = *len + 1;

    return 0;
}

int DeleteArray(int *array, int *len, int val)
{
    for (int i = 0; i < *len; i++) {
        if (array[i] == val) {
            for (int j = i; j + 1 < *len; j++) {
                array[j] = array[j + 1];
            }
            *len = *len - 1;
            return 0;
        }
    }

    return -1;
}

int UpdateArray(int *array, int len, int val, int updateVal)
{
    int location = GetLocationFromArray(array, len, val);
    if (location >= 0) {
        if (updateVal > val) {
            int end = location + 1;
            array[location] = updateVal;
            while (end < len && updateVal > array[end]) {
                array[end - 1] = array[end];
                array[end] = updateVal;
                end++;
            }
        } else if (updateVal < val) {
            int end = location - 1;
            array[location] = updateVal;
            while (end >= 0 && updateVal < array[end]) {
                array[end + 1] = array[end];
                array[end] = updateVal;
                end--;
            }
        }
        return 0;
    }

    return -1;
}

int SeletcArray(int *array, int len, int val)
{
    return GetLocationFromArray(array, len, val);
}

int DestoryArray(int *array)
{
    free(array);
    return 0;
}

void PrintfArray(int *array, int len)
{
    printf("[");
    for (int i = 0; i < len; i++) {
        printf("%d", array[i]);
        if (i < len - 1) {
            printf(",");
        }
    }
    printf("]\r\n");
}

int main(void)
{
    int *array = NULL;
    int maxLen = 1000;
    int len = 0;

    array = CreateArray(maxLen, &len);
    InsertArray(array, maxLen, &len, 1);
    InsertArray(array, maxLen, &len, 2);
    InsertArray(array, maxLen, &len, 2);
    InsertArray(array, maxLen, &len, 3);
    InsertArray(array, maxLen, &len, 3);
    InsertArray(array, maxLen, &len, 4);
    InsertArray(array, maxLen, &len, 6);
    DeleteArray(array, &len, 3);
    DeleteArray(array, &len, 2);
    PrintfArray(array, len);
    UpdateArray(array, len, 6, 5);
    PrintfArray(array, len);
    printf("select=%d\r\n", SeletcArray(array, len, 4));
    UpdateArray(array, len, 5, 0);
    PrintfArray(array, len);
    printf("select=%d\r\n", SeletcArray(array, len, 0));
    printf("select=%d\r\n", SeletcArray(array, len, 9));
    DestoryArray(array);

    return 0;
}

字符串 (String)

定义
全部为ascii字符组成,最后一位为'\0'

实现代码

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

char *CreateString(int maxLen, int *len)
{
    *len = 0;
    return (char *)malloc(maxLen * sizeof(char));
}

int InsertString(char *str, int maxLen, int *len, char c)
{
    if (*len + 1 >= maxLen) {
        return -1;
    }
    str[*len] = c;
    *len = *len + 1;
    str[*len] = '\0';
    return 0;
}

int DeleteString(char *str, int *len, char c)
{
    for (int i = 0; i < *len; i++) {
        if (str[i] == c) {
            for (int j = i; j + 1 < *len; j++) {
                str[j] = str[j + 1];
            }
            *len = *len - 1;
            str[*len] = '\0';
            return 0;
        }
    }

    return -1;
}

int UpdateString(char *str, int len, char c, char updateC)
{
    for (int i = 0; i < len; i++) {
        if (str[i] == c) {
            str[i] = updateC;
            return 0;
        }
    }

    return -1;
}

int SeletcString(char *str, int len, char c)
{
    for (int i = 0; i < len; i++) {
        if (str[i] == c) {
            return i;
        }
    }

    return -1;
}

int DestoryString(char *str)
{
    free(str);
    return 0;
}

void PrintfString(char *str)
{
    printf("\"%s\"\r\n", str);
}

int main(void)
{
    char *str = NULL;
    int maxLen = 1000;
    int len = 0;

    str = CreateString(maxLen, &len);
    InsertString(str, maxLen, &len, '1');
    PrintfString(str);
    InsertString(str, maxLen, &len, '2');
    PrintfString(str);
    InsertString(str, maxLen, &len, '3');
    PrintfString(str);
    InsertString(str, maxLen, &len, '3');
    PrintfString(str);
    InsertString(str, maxLen, &len, '4');
    PrintfString(str);
    InsertString(str, maxLen, &len, '6');
    PrintfString(str);
    DeleteString(str, &len, '3');
    PrintfString(str);
    UpdateString(str, len, '6', '5');
    PrintfString(str);
    printf("select=%d\r\n", SeletcString(str, len, '5'));
    printf("select=%d\r\n", SeletcString(str, len, '0'));
    DestoryString(str);
  
    return 0;
}

栈 (Stack)

普通栈 (Normal Stack)

定义
先进后出后进先出链状数据结构

实现代码

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

struct Stack {
    int *buf;
    int maxLen;
    int end;
};

struct Stack *CreateStack(int maxLen)
{
    struct Stack *s = (struct Stack *)malloc(sizeof(struct Stack));
    s->buf = (int *)malloc(maxLen * sizeof(int));
    s->maxLen = maxLen;
    s->end = -1;
    return s;
}

int PushStack(struct Stack *s, int val)
{
    if (s->end + 1 >= s->maxLen) {
        return -1;
    }
    s->buf[++s->end] = val;
    return 0;
}

int PopStack(struct Stack *s)
{
    if (s->end < 0) {
        return -1;
    }
    return s->buf[s->end--];
}

int DestoryStack(struct Stack *s)
{
    free(s->buf);
    free(s);
    return 0;
}

void PrintfStack(struct Stack *s)
{
    printf("maxLen=%d,end=%d,buf=[", s->maxLen, s->end);
    for (int i = 0; i <= s->end; i++) {
        printf("%d", s->buf[i]);
        if (i < s->end) {
            printf(",");
        }
    }
    printf("]\r\n");
}

int main(void)
{
    struct Stack *s = NULL;
    int maxLen = 1000;

    s = CreateStack(maxLen);
    PushStack(s, 3);
    PrintfStack(s);
    PushStack(s, 2);
    PrintfStack(s);
    PushStack(s, 1);
    PrintfStack(s);
    printf("pop=%d\r\n", PopStack(s));
    PrintfStack(s);
    printf("pop=%d\r\n", PopStack(s));
    PrintfStack(s);
    printf("pop=%d\r\n", PopStack(s));
    PrintfStack(s);
    printf("pop=%d\r\n", PopStack(s));
    PrintfStack(s);
    DestoryStack(s);
  
    return 0;
}

单调栈 (Monotonic Stack)

定义
每次新入元素后保持栈有序

实现代码

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

struct Stack {
    int *buf;
    int maxLen;
    int end;
};

struct Stack *CreateStack(int maxLen)
{
    struct Stack *s = (struct Stack *)malloc(sizeof(struct Stack));
    s->buf = (int *)malloc(maxLen * sizeof(int));
    s->maxLen = maxLen;
    s->end = -1;
    return s;
}

int PushStack(struct Stack *s, int val)
{
    if (s->end + 1 >= s->maxLen) {
        return -1;
    }

    int end = s->end + 1;
    while (end - 1 >= 0 && val < s->buf[end - 1]) {
        s->buf[end] = s->buf[end - 1];
        end--;
    }
    s->buf[end] = val;
    s->end += 1;
    return 0;
}

int PopStack(struct Stack *s)
{
    if (s->end < 0) {
        return -1;
    }
    return s->buf[s->end--];
}

int DestoryStack(struct Stack *s)
{
    free(s->buf);
    free(s);
    return 0;
}

void PrintfStack(struct Stack *s)
{
    printf("maxLen=%d,end=%d,buf=[", s->maxLen, s->end);
    for (int i = 0; i <= s->end; i++) {
        printf("%d", s->buf[i]);
        if (i < s->end) {
            printf(",");
        }
    }
    printf("]\r\n");
}

int main(void)
{
    struct Stack *s = NULL;
    int maxLen = 1000;

    s = CreateStack(maxLen);
    PushStack(s, 3);
    PrintfStack(s);
    PushStack(s, 2);
    PrintfStack(s);
    PushStack(s, 1);
    PrintfStack(s);
    printf("pop=%d\r\n", PopStack(s));
    PrintfStack(s);
    printf("pop=%d\r\n", PopStack(s));
    PrintfStack(s);
    printf("pop=%d\r\n", PopStack(s));
    PrintfStack(s);
    printf("pop=%d\r\n", PopStack(s));
    PrintfStack(s);
    DestoryStack(s);
  
    return 0;
}

最大频率栈 (Maximum Frequency Stack)

定义
出栈的时候返回出现频率最高的元素,如果频繁的元素不止一个,则返回最接近栈顶的元素

实现思路
通过哈希表记录每个值的数量,每次入栈+1 出栈-1
记录一个最大的频率值
每个频率值用一个栈

实现代码

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

struct Stack {
    int *buf;
    int maxLen;
    int end;
};

struct Stack *CreateStack(int maxLen)
{
    struct Stack *s = (struct Stack *)malloc(sizeof(struct Stack));
    s->buf = (int *)malloc(maxLen * sizeof(int));
    s->maxLen = maxLen;
    s->end = -1;
    return s;
}

int PushStack(struct Stack *s, int val)
{
    if (s->end + 1 >= s->maxLen) {
        return -1;
    }
    s->buf[++s->end] = val;
    return 0;
}

int PopStack(struct Stack *s)
{
    if (s->end < 0) {
        return -1;
    }
    return s->buf[s->end--];
}

int DestoryStack(struct Stack *s)
{
    free(s->buf);
    free(s);
    return 0;
}

void PrintfStack(struct Stack *s)
{
    printf("maxLen=%d,end=%d,buf=[", s->maxLen, s->end);
    for (int i = 0; i <= s->end; i++) {
        printf("%d", s->buf[i]);
        if (i < s->end) {
            printf(",");
        }
    }
    printf("]\r\n");
}

struct MaxFreqStack {
    int maxFreq;
    int curMaxFreq;
    int *intHashMap;
    struct Stack *stackTbl;
};

struct MaxFreqStack *CreateMaxFreqStack(int maxStackLen, int maxHashInt, int maxFreq)
{
    struct MaxFreqStack *mfs = (struct MaxFreqStack *)malloc(sizeof(struct MaxFreqStack));
    mfs->maxFreq = maxFreq;
    mfs->curMaxFreq = 0;
    mfs->intHashMap = (int *)malloc((maxHashInt + 1) * sizeof(int));
    memset(mfs->intHashMap, 0, (maxHashInt + 1) * sizeof(int));
    mfs->stackTbl = (struct Stack *)malloc((maxFreq + 1) * sizeof(struct Stack));
    memset(mfs->stackTbl, 0, (maxFreq + 1) * sizeof(struct Stack));
    for (int i = 0; i <= maxFreq; i++) {
        mfs->stackTbl[i].buf = (int *)malloc(maxStackLen * sizeof(int));
        mfs->stackTbl[i].maxLen = maxStackLen;
        mfs->stackTbl[i].end = -1;
    }
    return mfs;
}

int PushMaxFreqStack(struct MaxFreqStack *mfs, int val)
{
    mfs->intHashMap[val] += 1;
    if (mfs->intHashMap[val] > mfs->curMaxFreq) {
        mfs->curMaxFreq = mfs->intHashMap[val];
    }
    return PushStack(&mfs->stackTbl[mfs->intHashMap[val]], val);
}

int PopMaxFreqStack(struct MaxFreqStack *mfs)
{
    if (mfs->curMaxFreq <= 0) {
        return -1;
    }

    int ret = -1;
    while (mfs->curMaxFreq != 0) {
        ret = PopStack(&mfs->stackTbl[mfs->curMaxFreq]);
        if (ret == -1) {
            mfs->curMaxFreq -= 1;
        } else {
            mfs->intHashMap[ret] -= 1;
            break;
        }   
    }
    return ret;
}

int DestoryMaxFreqStack(struct MaxFreqStack *mfs)
{

    free(mfs->intHashMap);
    for (int i = 0; i <= mfs->maxFreq; i++) {
        free(mfs->stackTbl[i].buf);
    }
    free(mfs->stackTbl);
    free(mfs);
    return 0;
}

void PrintfMaxFreqStack(struct MaxFreqStack *mfs)
{
    printf("maxFreq=%d,curMaxFreq=%d\r\n", mfs->maxFreq, mfs->curMaxFreq);
    for (int i = 1; i <= mfs->curMaxFreq; i++) {
        printf("freq=%d,", i);
        PrintfStack(&mfs->stackTbl[i]);
    }
}

int main(void)
{
    struct MaxFreqStack *mfs = NULL;

    mfs = CreateMaxFreqStack(100, 100, 10);
    PrintfMaxFreqStack(mfs);

    PushMaxFreqStack(mfs, 1);
    PrintfMaxFreqStack(mfs);
    PushMaxFreqStack(mfs, 2);
    PrintfMaxFreqStack(mfs);
    PushMaxFreqStack(mfs, 3);
    PrintfMaxFreqStack(mfs);
    PushMaxFreqStack(mfs, 3);
    PrintfMaxFreqStack(mfs);
    PushMaxFreqStack(mfs, 3);
    PrintfMaxFreqStack(mfs);
    PushMaxFreqStack(mfs, 2);
    PrintfMaxFreqStack(mfs);
    printf("pop=%d\r\n", PopMaxFreqStack(mfs));
    PrintfMaxFreqStack(mfs);
    printf("pop=%d\r\n", PopMaxFreqStack(mfs));
    PrintfMaxFreqStack(mfs);
    printf("pop=%d\r\n", PopMaxFreqStack(mfs));
    PrintfMaxFreqStack(mfs);
    PushMaxFreqStack(mfs, 3);
    PrintfMaxFreqStack(mfs);
    printf("pop=%d\r\n", PopMaxFreqStack(mfs));
    PrintfMaxFreqStack(mfs);
    printf("pop=%d\r\n", PopMaxFreqStack(mfs));
    PrintfMaxFreqStack(mfs);
    printf("pop=%d\r\n", PopMaxFreqStack(mfs));
    PrintfMaxFreqStack(mfs);
    printf("pop=%d\r\n", PopMaxFreqStack(mfs));
    PrintfMaxFreqStack(mfs);
    printf("pop=%d\r\n", PopMaxFreqStack(mfs));
    PrintfMaxFreqStack(mfs);

    DestoryMaxFreqStack(mfs);
 
    return 0;
}

队列 (Queue)

普通队列 (Normal Queue)

定义
先进先出、后进后出

实现代码

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

struct Queue {
    int *buf;
    int maxLen;
    int start, end;
};

struct Queue *CreateQueue(int maxLen)
{
    struct Queue *q = (struct Queue *)malloc(sizeof(struct Queue));
    q->buf = (int *)malloc(maxLen * sizeof(int));
    q->maxLen = maxLen;
    q->start = -1;
    q->end = -1;
    return q;
}

int EnQueue(struct Queue *q, int val)
{
    if (q->end + 1 >= q->maxLen) {
        q->end = -1;
    }
    q->buf[++q->end] = val;
    return 0;
}

int DeQueue(struct Queue *q)
{
    if (q->start + 1>= q->maxLen) {
        q->start = -1;
    }
    if (q->start == q->end) {
        q->start = -1;
        q->end = -1;
        return -1;
    }
    return q->buf[++q->start];
}

int DestoryQueue(struct Queue *q)
{
    free(q->buf);
    free(q);
    return 0;
}

void PrintfQueue(struct Queue *q)
{
    printf("maxLen=%d,start=%d,end=%d,buf=[", q->maxLen, q->start, q->end);
    for (int i = q->start + 1; i <= q->end; i++) {
        printf("%d", q->buf[i]);
        if (i < q->end) {
            printf(",");
        }
    }
    printf("]\r\n");
}

int main(void)
{
    struct Queue *q = NULL;
    int maxLen = 1000;

    q = CreateQueue(maxLen);
    EnQueue(q, 1);
    PrintfQueue(q);
    EnQueue(q, 2);
    PrintfQueue(q);
    EnQueue(q, 3);
    PrintfQueue(q);
    printf("pop=%d\r\n", DeQueue(q));
    PrintfQueue(q);
    printf("pop=%d\r\n", DeQueue(q));
    PrintfQueue(q);
    printf("pop=%d\r\n", DeQueue(q));
    PrintfQueue(q);
    printf("pop=%d\r\n", DeQueue(q));
    PrintfQueue(q);
    DestoryQueue(q);
  
    return 0;
}

优先队列 (Priority Queue)

堆排序 博客园

定义
最大优先队列:无论入队顺序如何,都是当前最大的元素优先出队
最小优先队列:无论入队顺序如何,都是当前最小的元素优先出队

实现思路
利用二叉堆的思想。插入元素的时候上浮到合适位置;出队的时候,将原堆顶出队,把最后一个节点替换到堆顶,然后下沉到合适位置

实现代码

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

struct Queue {
    int *buf;
    int maxLen;
    int start, end;
};

static int GetParent(int pos)
{
    return (pos - 1) / 2;    
}

static int GetLeftChild(int pos)
{
    return (2 * pos + 1);    
}

static int GetRightChild(int pos)
{
    return (2 * pos + 2);    
}

static int swim(int *buf, int end)
{
    int pos = end;
    int parent = GetParent(pos);
    while (pos >= 0 && parent >= 0 && buf[pos] > buf[parent]) {
        int tmp = buf[pos];
        buf[pos] = buf[parent];
        buf[parent] = tmp;

        pos = parent;
        parent = GetParent(pos);
    }
    
    return 0;
}

static int sink(int *buf, int end)
{
    int pos = 0;
    int left = GetLeftChild(pos);
    int right = GetRightChild(pos);
    while (left <= end) {
        int maxChild = left;
        if (right <= end) {
            maxChild = (buf[left] > buf[right]) ? left : right;
        }
        if (buf[pos] >= buf[maxChild]) {
            break;
        }
        int tmp = buf[pos];
        buf[pos] = buf[maxChild];
        buf[maxChild] = tmp;

        pos = maxChild;
        left = GetLeftChild(pos);
        right = GetRightChild(pos);
    }
    
    return 0;
}

struct Queue *CreateQueue(int maxLen)
{
    struct Queue *q = (struct Queue *)malloc(sizeof(struct Queue));
    q->buf = (int *)malloc(maxLen * sizeof(int));
    q->maxLen = maxLen;
    q->start = -1;
    q->end = -1;
    return q;
}

int EnQueue(struct Queue *q, int val)
{
    if (q->end + 1 >= q->maxLen) {
        q->end = -1;
    }
    q->buf[++q->end] = val;
    swim(q->buf, q->end);
    return 0;
}

int DeQueue(struct Queue *q)
{
    if (q->start + 1 >= q->maxLen) {
        q->start = -1;
    }
    if (q->end < 0 || q->start == q->end) {
        q->start = -1;
        q->end = -1;
        return -1;
    }
    int max = q->buf[0];
    q->buf[0] = q->buf[q->end--];
    sink(q->buf, q->end);
    return max;
}

int DestoryQueue(struct Queue *q)
{
    free(q->buf);
    free(q);
    return 0;
}

void PrintfQueue(struct Queue *q)
{
    printf("maxLen=%d,start=%d,end=%d,buf=[", q->maxLen, q->start, q->end);
    for (int i = q->start + 1; i <= q->end; i++) {
        printf("%d", q->buf[i]);
        if (i < q->end) {
            printf(",");
        }
    }
    printf("]\r\n");
}

int main(void)
{
    struct Queue *q = NULL;
    int maxLen = 1000;

    q = CreateQueue(maxLen);
    EnQueue(q, 1);
    PrintfQueue(q);
    EnQueue(q, 2);
    PrintfQueue(q);
    EnQueue(q, 3);
    PrintfQueue(q);
    EnQueue(q, 4);
    PrintfQueue(q);
    EnQueue(q, 10);
    PrintfQueue(q);
    printf("pop=%d\r\n", DeQueue(q));
    PrintfQueue(q);
    printf("pop=%d\r\n", DeQueue(q));
    PrintfQueue(q);
    printf("pop=%d\r\n", DeQueue(q));
    PrintfQueue(q);
    printf("pop=%d\r\n", DeQueue(q));
    PrintfQueue(q);
    printf("pop=%d\r\n", DeQueue(q));
    PrintfQueue(q);
    printf("pop=%d\r\n", DeQueue(q));
    PrintfQueue(q);
    DestoryQueue(q);
  
    return 0;
}

单调队列 (Monotonic Queue)

定义
每次队列新入元素后保持有序

实现代码

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

struct Queue {
    int *buf;
    int maxLen;
    int start, end;
};

struct Queue *CreateQueue(int maxLen)
{
    struct Queue *q = (struct Queue *)malloc(sizeof(struct Queue));
    q->buf = (int *)malloc(maxLen * sizeof(int));
    q->maxLen = maxLen;
    q->start = -1;
    q->end = -1;
    return q;
}

int EnQueue(struct Queue *q, int val)
{
    if (q->end + 1 >= q->maxLen) {
        q->end = -1;
    }
    ++q->end;
    int pos = q->end;
    q->buf[pos] = val;
    while (pos - 1 > q->start && q->buf[pos - 1] > q->buf[pos]) {
        q->buf[pos] = q->buf[pos - 1];
        pos = pos - 1;
    }
    q->buf[pos] = val;
    return 0;
}

int DeQueue(struct Queue *q)
{
    if (q->start + 1>= q->maxLen) {
        q->start = -1;
    }
    if (q->start == q->end) {
        q->start = -1;
        q->end = -1;
        return -1;
    }
    return q->buf[++q->start];
}

int DestoryQueue(struct Queue *q)
{
    free(q->buf);
    free(q);
    return 0;
}

void PrintfQueue(struct Queue *q)
{
    printf("maxLen=%d,start=%d,end=%d,buf=[", q->maxLen, q->start, q->end);
    for (int i = q->start + 1; i <= q->end; i++) {
        printf("%d", q->buf[i]);
        if (i < q->end) {
            printf(",");
        }
    }
    printf("]\r\n");
}

int main(void)
{
    struct Queue *q = NULL;
    int maxLen = 1000;

    q = CreateQueue(maxLen);
    EnQueue(q, 1);
    PrintfQueue(q);
    EnQueue(q, 2);
    PrintfQueue(q);
    EnQueue(q, 3);
    PrintfQueue(q);
    printf("pop=%d\r\n", DeQueue(q));
    PrintfQueue(q);
    printf("pop=%d\r\n", DeQueue(q));
    PrintfQueue(q);
    printf("pop=%d\r\n", DeQueue(q));
    PrintfQueue(q);
    printf("pop=%d\r\n", DeQueue(q));
    PrintfQueue(q);
    DestoryQueue(q);
  
    return 0;
}

例子
单调队列解决滑动窗口问题

#include <limits.h>
void QEnter(int* q, int *qLen, int value)
{
    int cur = (*qLen) - 1;
    
    while (cur >= 0 && q[cur] < value) {
        cur--;
    }
    
    q[cur + 1] = value;
    *qLen = cur + 2;
}

void QOut(int* q, int *qLen, int value)
{
    int cur = 0;
    
    if (qLen > 0 && value == q[0]) {
        while (cur < *qLen) {
            q[cur] = q[cur + 1];
            cur++;
        }
        (*qLen) -= 1;
    }
}

int QMax(int* q, int *qLen)
{
   return q[0]; 
}

int* maxInWindows(int* num, int numLen, int size, int* returnSize ) {
    // write code here
    int left = 0, right = 0;
    *returnSize = numLen - size + 1;
    int *outBuf = malloc((*returnSize) * sizeof(int));
    int outPoi = 0;
    int qBuf[numLen];
    int qLen = 0;
    
    for (right = 0; right < numLen; right++) {
        QEnter(qBuf, &qLen, num[right]);
        /*
        printf("[");
        for (int i = 0; i < qLen; i++) {
            printf("%d ", qBuf[i]);
        }
        printf("]\r\n");
        */
        
        if (right - left == size - 1) {
            outBuf[outPoi++] = QMax(qBuf, &qLen);
            QOut(qBuf, &qLen, num[left]);
            left++;
        }
        
    }
    
    return outBuf;
}

链表 (Linked List)

单向链表 (Single Linked List)

实现代码

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

struct LinkedList {
    int val;
    struct LinkedList *next;
};

static struct LinkedList *CreateLinkedList(int val)
{
    struct LinkedList *node = (struct LinkedList *)malloc(sizeof(struct LinkedList));
    node->val = val;
    node->next = NULL;
    return node;
}

int AddLinkedList(struct LinkedList **head, int val)
{
    struct LinkedList *node = CreateLinkedList(val);
    if (*head == NULL) {
        *head = node;
    } else {
        struct LinkedList *pre = *head;
        struct LinkedList *cur = (*head)->next;
        while (cur != NULL) {
            pre = cur;
            cur = cur->next;
        }
        pre->next = node;
    }
    return 0;
}

int DelLinkedList(struct LinkedList **head, int val)
{
    if (*head != NULL) {
        struct LinkedList dummy;
        struct LinkedList *pre;
        struct LinkedList *cur;
        dummy.next = *head;
        pre = &dummy;
        cur = *head;
        while (cur != NULL) {
            if (cur->val == val) {
                pre->next = cur->next;
                free(cur);
                cur = NULL;
                *head = dummy.next;
                break;
            }
            pre = cur;
            cur = cur->next;
        }
    }
    return 0;
}

int DestoryLinkedList(struct LinkedList **head)
{
    if (*head != NULL) {
        struct LinkedList *pre = *head;
        struct LinkedList *cur = *head;
        while (cur != NULL) {
            pre = cur;
            cur = cur->next;
            free(pre);
            pre = NULL;
        }
        *head = NULL;
    }
    return 0;
}

void PrintfLinkedList(struct LinkedList *head)
{
    printf("head=%p, buf=[", head);
    if (head != NULL) {
        struct LinkedList *cur = head;
        while (cur != NULL) {
            printf("%d", cur->val);
            cur = cur->next;
            if (cur != NULL) {
                printf(",");
            }
        }
    }
    printf("]\r\n");
}

int main(void)
{
    struct LinkedList *head = NULL;

    AddLinkedList(&head, 1);
    PrintfLinkedList(head);
    AddLinkedList(&head, 2);
    PrintfLinkedList(head);
    AddLinkedList(&head, 3);
    PrintfLinkedList(head);
    DelLinkedList(&head, 1);
    PrintfLinkedList(head);
    DelLinkedList(&head, 2);
    PrintfLinkedList(head);
    DelLinkedList(&head, 3);
    PrintfLinkedList(head);
    DelLinkedList(&head, 3);
    PrintfLinkedList(head);
    DestoryLinkedList(&head);

    return 0;
}

循环链表 (Circular Linked List)

定义
尾节点指向头结点
实现代码

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

struct LinkedList {
    int val;
    struct LinkedList *next;
};

static struct LinkedList *CreateLinkedList(int val)
{
    struct LinkedList *node = (struct LinkedList *)malloc(sizeof(struct LinkedList));
    node->val = val;
    node->next = NULL;
    return node;
}

int AddLinkedList(struct LinkedList **head, int val)
{
    struct LinkedList *node = CreateLinkedList(val);
    if (*head == NULL) {
        *head = node;
        node->next = *head;
    } else {
        struct LinkedList *pre = *head;
        struct LinkedList *cur = (*head)->next;
        while (cur != *head) {
            pre = cur;
            cur = cur->next;
        }
        pre->next = node;
        node->next = *head;
    }
    return 0;
}

int DelLinkedList(struct LinkedList **head, int val)
{
    if (*head != NULL) {
        struct LinkedList *pre;
        struct LinkedList *cur;
        pre = *head;
        cur = (*head)->next;
        while (cur != *head) {
            if (cur->val == val) {
                break;
            }
            pre = cur;
            cur = cur->next;
        }
        if (cur->val == val) {
            pre->next = cur->next;
            if (cur == *head) {
                *head = (pre == *head) ? (NULL) : (pre);
            }
            free(cur);
        }
    }
    return 0;
}

int DestoryLinkedList(struct LinkedList **head)
{
    if (*head != NULL) {
        struct LinkedList *pre = *head;
        struct LinkedList *cur = (*head)->next;
        while (cur != *head) {
            pre = cur;
            cur = cur->next;
            free(pre);
            pre = NULL;
        }
        *head = NULL;
    }
    return 0;
}

void PrintfLinkedList(struct LinkedList *head)
{
    printf("head=%p, buf=[", head);
    if (head != NULL) {
        struct LinkedList *pre = head;
        struct LinkedList *cur = head->next;
        while (cur != head) {
            printf("%d,", pre->val);
            pre = cur;
            cur = cur->next;
        }
        printf("%d", pre->val);
    }
    printf("]\r\n");
}

int main(void)
{
    struct LinkedList *head = NULL;

    AddLinkedList(&head, 1);
    PrintfLinkedList(head);
    AddLinkedList(&head, 2);
    PrintfLinkedList(head);
    AddLinkedList(&head, 3);
    PrintfLinkedList(head);
    DelLinkedList(&head, 1);
    PrintfLinkedList(head);
    DelLinkedList(&head, 2);
    PrintfLinkedList(head);
    DelLinkedList(&head, 3);
    PrintfLinkedList(head);
    DelLinkedList(&head, 3);
    PrintfLinkedList(head);
    DestoryLinkedList(&head);

    return 0;
}

双向链表 (Doubly Linked List)

实现代码

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

struct LinkedList {
    int val;
    struct LinkedList *prior;
    struct LinkedList *next;
};

static struct LinkedList *CreateLinkedList(int val)
{
    struct LinkedList *node = (struct LinkedList *)malloc(sizeof(struct LinkedList));
    node->val = val;
    node->prior = NULL;
    node->next = NULL;
    return node;
}

int AddLinkedList(struct LinkedList **head, int val)
{
    struct LinkedList *node = CreateLinkedList(val);
    if (*head == NULL) {
        *head = node;
    } else {
        struct LinkedList *pre = *head;
        struct LinkedList *cur = (*head)->next;
        while (cur != NULL) {
            pre = cur;
            cur = cur->next;
        }
        pre->next = node;
        node->prior = pre;
    }
    return 0;
}

int DelLinkedList(struct LinkedList **head, int val)
{
    if (*head != NULL) {
        struct LinkedList dummy;
        struct LinkedList *pre;
        struct LinkedList *cur;
        dummy.next = *head;
        pre = &dummy;
        cur = *head;
        while (cur != NULL) {
            if (cur->val == val) {
                pre->next = cur->next;
                if (cur->next != NULL) {
                    cur->next->prior = pre;
                }
                free(cur);
                cur = NULL;
                *head = dummy.next;
                break;
            }
            pre = cur;
            cur = cur->next;
        }
    }
    return 0;
}

int DestoryLinkedList(struct LinkedList **head)
{
    if (*head != NULL) {
        struct LinkedList *pre = *head;
        struct LinkedList *cur = *head;
        while (cur != NULL) {
            pre = cur;
            cur = cur->next;
            free(pre);
            pre = NULL;
        }
        *head = NULL;
    }
    return 0;
}

void PrintfLinkedList(struct LinkedList *head)
{
    printf("head=%p, buf=[", head);
    if (head != NULL) {
        struct LinkedList *cur = head;
        while (cur != NULL) {
            printf("%d", cur->val);
            cur = cur->next;
            if (cur != NULL) {
                printf(",");
            }
        }
    }
    printf("]\r\n");
}

int main(void)
{
    struct LinkedList *head = NULL;

    AddLinkedList(&head, 1);
    PrintfLinkedList(head);
    AddLinkedList(&head, 2);
    PrintfLinkedList(head);
    AddLinkedList(&head, 3);
    PrintfLinkedList(head);
    DelLinkedList(&head, 1);
    PrintfLinkedList(head);
    DelLinkedList(&head, 2);
    PrintfLinkedList(head);
    DelLinkedList(&head, 3);
    PrintfLinkedList(head);
    DelLinkedList(&head, 3);
    PrintfLinkedList(head);
    DestoryLinkedList(&head);

    return 0;
}

双向循环链表 (Doubly Circular Linked List)

树状数据结构 (Tree Data Structure)

哈希表(Hash Table)

  • 普通哈希表(Hash Table)
    参考

实现代码

静态实现

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

#define MAX_HASH_MAP_SIZE 1000
#define MAX_HASH_MAP_LINK_LEN 100
#define MAX_KEY_LEN 30
#define MAX_VALUE_LEN 30
struct HashMapNode {
    char key[MAX_KEY_LEN];
    char value[MAX_VALUE_LEN];
};

struct HashMapNode g_HashMap[MAX_HASH_MAP_SIZE][MAX_HASH_MAP_LINK_LEN];

void InitHashMap(void)
{   
    memset(g_HashMap, 0, sizeof(g_HashMap));
}

static int KeyToIndex(char* key)
{
    int index = 0;
    while (*key != '\0') {
        index += *key;
        key++;
    }
    
    return index;
}

struct HashMapNode *FindKeyEmptyNode(char *key)
{
    int index = KeyToIndex(key);
    struct HashMapNode *head = g_HashMap[index];
    for (int i = 0; i < MAX_HASH_MAP_LINK_LEN; i++) {
        if (head[i].key[0] == '\0') {
            return &head[i];
        }
    }

    return NULL;
}

struct HashMapNode *FindKeyNode(char *key)
{
    int index = KeyToIndex(key);
    struct HashMapNode *head = g_HashMap[index];
    for (int i = 0; i < MAX_HASH_MAP_LINK_LEN; i++) {
        if (strcmp(head[i].key, key) == 0) {
            return &head[i];
        }
    }

    return NULL;
}

int AddHashMap(char *key, char *value)
{
    struct HashMapNode *node = FindKeyEmptyNode(key);
    strcpy(node->key, key);
    strcpy(node->value, value);

    return 0;
}

int DelHashMap(char *key)
{
    struct HashMapNode *node = FindKeyNode(key);
    memset(node, 0, sizeof(struct HashMapNode));
    return 0;
}
char *SearchHashMap(char *key)
{
    struct HashMapNode *node = FindKeyNode(key);
    return node->value;
}

int DestoryHashMap(void)
{
    return 0;
}

void PrintfHashMap(void)
{
    printf("HaspMap=[\r\n");
    for (int i = 0; i < MAX_HASH_MAP_SIZE; i++) {
        bool isEmpty = true;
        for (int j = 0; j < MAX_HASH_MAP_LINK_LEN; j++) {
            if (g_HashMap[i][j].key[0] != '\0') {
                isEmpty = false;
                break;
            }
        }
        if (!isEmpty) {
            printf("HashKey=%d [", i);
            for (int j = 0; j < MAX_HASH_MAP_LINK_LEN; j++) {
                if (g_HashMap[i][j].key[0] != '\0') {
                    printf("{%s->%s} ", g_HashMap[i][j].key, g_HashMap[i][j].value);
                }
            }
            printf("]\r\n");
        }
    }
    printf("]\r\n");
}

int main(void)
{
    InitHashMap();
    AddHashMap("jone", "60");
    PrintfHashMap();
    AddHashMap("david", "23");
    PrintfHashMap();
    AddHashMap("bluse", "34");
    PrintfHashMap();
    AddHashMap("mike", "100");
    PrintfHashMap();
    AddHashMap("mijf", "23");
    PrintfHashMap();
    printf("jone=%s\r\n", SearchHashMap("jone"));
    DelHashMap("david");
    PrintfHashMap();
    DestoryHashMap();
    
    return 0;
}

二叉树(Binary Tree)

参考

普通二叉树 (Binary Tree)

实现代码

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

struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
};

static struct TreeNode *CreateTreeNode(int val)
{
    struct TreeNode *node = (struct TreeNode *)malloc(sizeof(struct TreeNode));
    node->val = val;
    node->left = NULL;
    node->right = NULL;
    return node;
}

int AddTreeNode(struct TreeNode **root, int val)
{
    struct TreeNode *node = CreateTreeNode(val);
    if (*root == NULL) {
        *root = node;
    } else {
        struct TreeNode *nextQueue[100];
        int nextLen = 0;
        struct TreeNode *curQueue[100];
        int curLen = 0;
        curQueue[curLen++] = *root;
        while (curLen > 0) {
            bool isFind = false;
            for (int cur = 0; cur < curLen; cur++) {
                if (curQueue[cur]->left == NULL) {
                    curQueue[cur]->left = node;
                    isFind = true;
                    break;
                }
                nextQueue[nextLen++] = curQueue[cur]->left;
                if (curQueue[cur]->right == NULL) {
                    curQueue[cur]->right = node;
                    isFind = true;
                    break;
                }
                nextQueue[nextLen++] = curQueue[cur]->right;
            }
            
            if (isFind) {
                curLen = 0;
            } else {
                memcpy(curQueue, nextQueue, nextLen * sizeof(struct TreeNode *));
                curLen = nextLen;
                nextLen = 0;
            }
        }
    }
    return 0;
}

int DelTreeNode(struct TreeNode **root, int val)
{
    if (*root != NULL) {
        struct TreeNode *findFather = NULL;
        struct TreeNode *find = NULL;
        struct TreeNode *endFather = NULL;
        struct TreeNode *end = *root;
        struct TreeNode *nextQueue[100];
        int nextLen = 0;
        struct TreeNode *curQueue[100];
        int curLen = 0;
        curQueue[curLen++] = *root;
        if ((*root)->val == val) {
            if (findFather == NULL) {
                findFather = NULL;
                find = *root;
            }
        }
        while (curLen > 0) {
            for (int cur = 0; cur < curLen; cur++) {
                if (curQueue[cur]->left != NULL) {
                    nextQueue[nextLen++] = curQueue[cur]->left;
                    if (curQueue[cur]->left->val == val) {
                        if (findFather == NULL) {
                            findFather = curQueue[cur];
                            find = curQueue[cur]->left;
                        }
                    }
                    if (curQueue[cur]->left->left == NULL && curQueue[cur]->left->right == NULL) {
                        endFather = curQueue[cur];
                        end = curQueue[cur]->left;
                    }
                }
                if (curQueue[cur]->right != NULL) {
                    nextQueue[nextLen++] = curQueue[cur]->right;
                    if (curQueue[cur]->right->val == val) {
                        if (findFather == NULL) {
                            findFather = curQueue[cur];
                            find = curQueue[cur]->right;
                        }
                    }
                    if (curQueue[cur]->right->left == NULL && curQueue[cur]->right->right == NULL) {
                        endFather = curQueue[cur];
                        end = curQueue[cur]->right;
                    }
                }
                
            }
            
            memcpy(curQueue, nextQueue, nextLen * sizeof(struct TreeNode *));
            curLen = nextLen;
            nextLen = 0;
        }
        
        if (find != NULL) {
            if (endFather != NULL) {
                if (endFather->left == end) {
                    endFather->left = NULL;
                }
                if (endFather->right == end) {
                    endFather->right = NULL;
                }
            }
            if (findFather != NULL) {
                if (findFather->left == find) {
                    findFather->left = end;
                }
                if (findFather->right == find) {
                    findFather->right = end;
                }
            }
            end->left = find->left;
            end->right = find->right;
            if (find == *root) {
                if (endFather == NULL) {
                    *root = NULL;
                } else {
                    *root = end;
                }
            }
                
            free(find);
        }
    }
    return 0;
}

int DestoryTreeNode(struct TreeNode **root)
{
    if (*root != NULL) {
        struct TreeNode *nextQueue[100];
        int nextLen = 0;
        struct TreeNode *curQueue[100];
        int curLen = 0;
        while (curLen > 0) {
            for (int cur = 0; cur < curLen; cur++) {
                if (curQueue[cur]->left != NULL) {
                    nextQueue[nextLen++] = curQueue[cur]->left;
                }
                if (curQueue[cur]->right != NULL) {
                    nextQueue[nextLen++] = curQueue[cur]->right;
                }
                free(curQueue[cur]);
            }

            memcpy(curQueue, nextQueue, nextLen * sizeof(struct TreeNode *));
            curLen = nextLen;
            nextLen = 0;
        }
        *root = NULL;
    }
    return 0;
}

void PrintfTreeNode(struct TreeNode *root)
{
    printf("root=%p, buf=[", root);
    if (root != NULL) {
        struct TreeNode *nextQueue[100];
        int nextLen = 0;
        struct TreeNode *curQueue[100];
        int curLen = 0;
        curQueue[curLen++] = root;
        while (curLen > 0) {
            for (int cur = 0; cur < curLen; cur++) {
                if (curQueue[cur]->left != NULL) {
                    nextQueue[nextLen++] = curQueue[cur]->left;
                }
                if (curQueue[cur]->right != NULL) {
                    nextQueue[nextLen++] = curQueue[cur]->right;
                }
                printf("%d", curQueue[cur]->val);
                if (!(cur == curLen - 1 && nextLen == 0)) {
                    printf(",");
                }
            }

            memcpy(curQueue, nextQueue, nextLen * sizeof(struct TreeNode *));
            curLen = nextLen;
            nextLen = 0;
        }
    }
    printf("]\r\n");
}

int main(void)
{
    struct LinkedList *root = NULL;

    AddTreeNode(&root, 1);
    PrintfTreeNode(root);
    AddTreeNode(&root, 2);
    PrintfTreeNode(root);
    AddTreeNode(&root, 3);
    PrintfTreeNode(root);
    AddTreeNode(&root, 4);
    PrintfTreeNode(root);
    AddTreeNode(&root, 5);
    PrintfTreeNode(root);
    PrintfTreeNode(root);
    AddTreeNode(&root, 6);
    PrintfTreeNode(root);
    DelTreeNode(&root, 1);
    PrintfTreeNode(root);
    DelTreeNode(&root, 2);
    PrintfTreeNode(root);
    DelTreeNode(&root, 3);
    PrintfTreeNode(root);
    DelTreeNode(&root, 6);
    PrintfTreeNode(root);
    DelTreeNode(&root, 5);
    PrintfTreeNode(root);
    DelTreeNode(&root, 4);
    PrintfTreeNode(root);
    DelTreeNode(&root, 3);
    PrintfTreeNode(root);
    DestoryTreeNode(&root);

    return 0;
}

字典树 (Trie)

参考
参考

实现代码
静态实现

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

#define MAX_TRIE_SIZE 10000
#define ASCII_SIZE 256

struct TrieNode {
    int next;
    int cnt;
    bool isEnd;
};
struct TrieNode g_trie[MAX_TRIE_SIZE][ASCII_SIZE];
static int g_nextEmptyNode;

void InitTrie(void)
{
    memset(g_trie, 0, sizeof(g_trie));
    g_nextEmptyNode = 0;
}

int SearchTrie(char *str)
{
    int sLen = strlen(str);
    int root = 0;
    for (int i = 0; i < sLen; i++) {
        if (g_trie[root][str[i]].next == 0) {
            return -1;
        }
        root = g_trie[root][str[i]].next ;
    }

    return g_trie[root][str[sLen - 1]].isEnd ? 0 : -1;
}

int AddTrie(char *str)
{
    int sLen = strlen(str);
    int root = 0;
    for (int i = 0; i < sLen; i++) {
        if (g_trie[root][str[i]].next == 0) {
            g_trie[root][str[i]].next = ++g_nextEmptyNode;
        }
        root = g_trie[root][str[i]].next;
        if (i == sLen - 1) {
            g_trie[root][str[i]].isEnd = true;
        } else {
            g_trie[root][str[i]].cnt++;
        }
    }

    return 0;
}

int DelTrie(char *str)
{
    if (SearchTrie(str) != 0) {
        return -1;
    }
    int sLen = strlen(str);
    int root = 0;
    for (int i = 0; i < sLen; i++) {
        g_trie[root][str[i]].cnt--;
        root = g_trie[root][str[i]].next;
    }
    g_trie[root][str[sLen - 1]].isEnd = false;
    return 0;
}

int GetPrefixWordAmountFormTrie(char *prefix)
{
    int sLen = strlen(prefix);
    int root = 0;
    for (int i = 0; i < sLen; i++) {
        g_trie[root][prefix[i]].cnt--;
        root = g_trie[root][prefix[i]].next;
    }
    return g_trie[root][prefix[sLen - 1]].cnt;
}
int DestoryTrie(void)
{
    return 0;
}

void PrintfTrieRecursive(int root, int curDepth, char *stack)
{
    for (int i = 0; i < ASCII_SIZE; i++) {
        if (g_trie[root][i].next == 0) {
            continue;
        }
        stack[curDepth] = i;
        if (g_trie[g_trie[root][i].next][i].isEnd) {
            stack[curDepth + 1] = '\0';
            printf("%s\r\n", stack);
        }
        PrintfTrieRecursive(g_trie[root][i].next, curDepth + 1, stack);
    }
}

void PrintfTrie(void)
{
    printf("buf=[\r\n");
    char stack[100];
    PrintfTrieRecursive(0, 0, stack);
    printf("]\r\n");
}

int main(void)
{
    InitTrie();
    
    AddTrie("aaa");
    PrintfTrie();
    printf("GetPrefixWordAmountFormTrie=%d\r\n", GetPrefixWordAmountFormTrie("a"));
    AddTrie("aba");
    PrintfTrie();
    DelTrie("aaa");
    DelTrie("aaa");
    printf("GetPrefixWordAmountFormTrie=%d\r\n", GetPrefixWordAmountFormTrie("a"));
    PrintfTrie();
    AddTrie("aab");
    printf("GetPrefixWordAmountFormTrie=%d\r\n", GetPrefixWordAmountFormTrie("a"));
    PrintfTrie();
    AddTrie("zab");
    PrintfTrie();
    printf("GetPrefixWordAmountFormTrie=%d\r\n", GetPrefixWordAmountFormTrie("za"));
    return 0;
}

动态实现

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

#define ASCII_SIZE 256
struct TrieNode {
    int cnt;
    bool isEnd;
    struct TrieNode *next[ASCII_SIZE];
};

struct TrieNode *CreateTrieNode(void)
{
    struct TrieNode *node = (struct TrieNode *)malloc(sizeof(struct TrieNode));
    node->cnt = 0;
    node->isEnd = false;
    for (int i = 0; i < ASCII_SIZE; i++) {
        node->next[i] = NULL;
    }

    return node;
}

int SearchTrie(struct TrieNode *root, char *str)
{
    if (root == NULL) {
        return -1;
    }

    int sLen = strlen(str);
    struct TrieNode *cur = root;
    for (int i = 0 ; i < sLen; i++) {
        cur = cur->next[str[i]];
        if (cur == NULL) {
            return -1;
        }
        
        if (i == sLen - 1) {
            if (!cur->isEnd) {
                return -1;
            }
        } else {
            if(cur->cnt == 0) {
                return -1;   
            }
        }
    }

    return 0;
}

int AddTrie(struct TrieNode **root, char *str)
{
    int sLen = strlen(str);

    if (*root == NULL) {
        *root = CreateTrieNode();
    }
    if (SearchTrie(*root, str) == 0) {
        return 0;
    }

    struct TrieNode *cur = *root;
    for (int i = 0 ; i < sLen; i++) {
        if (cur->next[str[i]] == NULL) {
            cur->next[str[i]] = CreateTrieNode();
        }
        cur = cur->next[str[i]];
        
        if (i == sLen - 1) {
            cur->isEnd = true;
        } else {
            cur->cnt += 1;
        }
    }
    return 0;
}

int DelTrie(struct TrieNode **root, char *str)
{
    if (*root == NULL) {
        return -1;
    }
    if (SearchTrie(*root, str) != 0) {
        return -1;
    }
    
    int sLen = strlen(str);
    struct TrieNode *cur = *root;
    for (int i = 0 ; i < sLen; i++) {
        cur = cur->next[str[i]];

        if (i == sLen - 1) {
            cur->isEnd = false;
        } else {
            cur->cnt -= 1;
        }
    }
    return 0;
}

int GetPrefixWordAmountFormTrie(struct TrieNode *root, char *prefix)
{
    if (root == NULL) {
        return -1;
    }

    int sLen = strlen(prefix);
    struct TrieNode *cur = root;
    for (int i = 0 ; i < sLen; i++) {
        cur = cur->next[prefix[i]];
        if (cur == NULL) {
            return -1;
        }

        if (i == sLen - 1) {
            return cur->cnt;
        }
    }

    return 0;
}
int DestoryTrie(struct TrieNode **root)
{
    if (*root == NULL) {
        return 0;
    }
    struct TrieNode *cur = *root;
    for (int i = 0; i < ASCII_SIZE; i++) {
        if (cur->next[i] != NULL) {
            DestoryTrie(&cur->next[i]);
            free(cur->next[i]);
        }
    }
    free(*root);
    *root = NULL;
    return 0;
}

void PrintfTrieRecursive(struct TrieNode *root, int curDepth, char *stack)
{
    for (int i = 0; i < ASCII_SIZE; i++) {
        if (root->next[i] == NULL) {
            continue;
        }
        if (root->next[i]->cnt == 0 && !root->next[i]->isEnd) {
            continue;
        }
        stack[curDepth] = i;
        if (root->next[i]->isEnd) {
            stack[curDepth + 1] = '\0';
            printf("%s\r\n", stack);
        }
        PrintfTrieRecursive(root->next[i], curDepth + 1, stack);
    }
}

void PrintfTrie(struct TrieNode *root)
{
    printf("root=%p, buf=[\r\n", root);
    if (root != NULL) {
        char stack[100];
        PrintfTrieRecursive(root, 0, stack);
    }
    printf("]\r\n");
}

int main(void)
{
    struct TrieNode *root = NULL;

    AddTrie(&root, "aaa");
    PrintfTrie(root);
    AddTrie(&root, "aaf");
    PrintfTrie(root);
    AddTrie(&root, "abz");
    PrintfTrie(root);
    AddTrie(&root, "zas");
    PrintfTrie(root);
    AddTrie(&root, "zzz");
    PrintfTrie(root);
    AddTrie(&root, "zdsadasdas");
    PrintfTrie(root);
    AddTrie(&root, "dsadas");
    PrintfTrie(root);   
    DelTrie(&root, "zzz");
    PrintfTrie(root);
    DelTrie(&root, "dsadas");
    PrintfTrie(root);
    DelTrie(&root, "zdsadasdas");
    PrintfTrie(root);
    DelTrie(&root, "zas");
    PrintfTrie(root);
    DelTrie(&root, "abc");
    PrintfTrie(root);
    DelTrie(&root, "aaf");
    PrintfTrie(root);
    DelTrie(&root, "aaa");
    PrintfTrie(root);
    DestoryTrie(&root);

    return 0;
}

并查集 (Disjoint Set Union)

参考
参考

代码实现

静态实现

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

#define MAX_SIZE 10
int g_Buf[MAX_SIZE];

void InitDSU(void)
{   
    for (int i = 0; i < MAX_SIZE; i++) {
        g_Buf[i] = i;
    }
}

int FindDSU(int child)
{
    int root = child;
    while (g_Buf[root] != root) {
        root = g_Buf[root];
    }
    
    int cur = child;
    while (g_Buf[cur] != cur) {
        int next = g_Buf[cur];
        g_Buf[cur] = root;
        cur = next;
    }
    return root;
}

int UnionDSU(int val1, int val2)
{
    int root1 = FindDSU(val1);
    int root2 = FindDSU(val2);
    
    if (root1 == root2) {
        return 0;
    }
    g_Buf[root1] = root2;
    return 0;
}

int IsConnectedDSU(int val1, int val2)
{
    int root1 = FindDSU(val1);
    int root2 = FindDSU(val2);
    
    return (root1 == root2) ? 0 : -1;
}

int PrintfLinkedNumDSU(void)
{
    int num = 0;
    for (int i = 0; i < MAX_SIZE; i++) {
        if (i == g_Buf[i]) {
            num++;
        }
    }
    printf("PrintfLinkedNumDSU num=%d\r\n", num);

    return num;
}

int DestoryDSU(void)
{
    return 0;
}

void PrintfDSU(void)
{
    printf("DUS=");
    for (int i = 0; i < MAX_SIZE; i++) {
        printf("{%d->%d} ", i, g_Buf[i]);
    }
    printf("\r\n");
}

int main(void)
{
    InitDSU();
    PrintfDSU();
    UnionDSU(1, 2);
    PrintfDSU();
    UnionDSU(2, 3);
    PrintfDSU();
    UnionDSU(4, 5);
    PrintfDSU();
    UnionDSU(5, 6);
    PrintfDSU();
    UnionDSU(6, 3);
    PrintfDSU();
    UnionDSU(9, 1);
    PrintfDSU();
    UnionDSU(8, 6);
    PrintfDSU();
    UnionDSU(0, 7);
    PrintfDSU();
    UnionDSU(7, 0);
    PrintfDSU();
    UnionDSU(0, 9);
    PrintfDSU();
    PrintfLinkedNumDSU();
    DestoryDSU();
    return 0;
}

动态实现

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

struct DSUNode {
    int val;
    int cnt;
    struct DSUNode *parent;
};

struct DSUNode* CreateDSU(int *buf, int len)
{
    struct DSUNode* head = malloc(len * sizeof(struct DSUNode));
    
    for (int i = 0; i < len; i++) {
        head[i].val = buf[i];
        head[i].cnt = 1;
        head[i].parent = &head[i];
    }
    
    return head;
}

struct DSUNode* FindDSU(struct DSUNode* child)
{
    struct DSUNode* root = child;
    while (root->parent != root) {
        root = root->parent;
    }
    struct DSUNode* cur = child;
    while (cur->parent != cur) {
        struct DSUNode* parent = cur->parent;
        cur->parent = root;
        cur = parent;
    }

    return root;
}

int UnionDSU(struct DSUNode* head, int len, int val1, int val2)
{
    struct DSUNode *val1Node = NULL, *val2Node = NULL;
    for (int i = 0; i < len; i++) {
        if (head[i].val == val1) {
            val1Node = &head[i];
        }
        if (head[i].val == val2) {
            val2Node = &head[i];
        }
        if (val1Node != NULL && val2Node != NULL) {
            break;
        }
    }
    if (val1Node == NULL || val2Node == NULL) {
        return -1;
    }
    struct DSUNode *val1Root = FindDSU(val1Node);
    struct DSUNode *val2Root = FindDSU(val2Node);
    if (val1Root == val2Root) {
        return 0;
    }
    if (val1Root->cnt < val2Root->cnt) {
        val1Root->parent = val2Root;
        val2Root->cnt += val1Root->cnt;
    } else {
        val2Root->parent = val1Root;
        val1Root->cnt += val2Root->cnt;
    }
    return 0;
}

int IsConnectedDSU(struct DSUNode* head, int len, int val1, int val2)
{
    struct DSUNode *val1Node = NULL, *val2Node = NULL;
    for (int i = 0; i < len; i++) {
        if (head[i].val == val1) {
            val1Node= &head[i];
        }
        if (head[i].val == val2) {
            val2Node= &head[i];
        }
        if (val1Node != NULL && val2Node != NULL) {
            break;
        }
    }

    if (val1Node == NULL || val2Node == NULL) {
        return -1;
    }
    struct DSUNode *val1Root = FindDSU(val1Node);
    struct DSUNode *val2Root = FindDSU(val1Node);
    
    return (val1Root == val2Root) ? 0 : -1;
}

int PrintfLinkedNumDSU(struct DSUNode* head, int len)
{
    int num = 0;
    for (int i = 0; i < len; i++) {
        if (head[i].parent == &head[i]) {
            num++;
            printf("num=%d,cnt=%d\r\n", num, head[i].cnt);
        }
    }

    return num;
}

int DestoryDSU(struct DSUNode* head)
{
    free(head);
    return 0;
}

void PrintfDSU(struct DSUNode* head, int len)
{
    printf("DUS=");
    for (int i = 0; i < len; i++) {
        printf("{%d->%d} ", head[i].val, head[i].parent->val);
    }
    printf("\r\n");
}

int main(void)
{
    int buf[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    int len = sizeof(buf) / sizeof(int);
    struct DSUNode *head = CreateDSU(buf, len);
    PrintfDSU(head, len);
    
    UnionDSU(head, len, 1, 2);
    PrintfDSU(head, len);
    UnionDSU(head, len, 2, 3);
    PrintfDSU(head, len);
    UnionDSU(head, len, 4, 5);
    PrintfDSU(head, len);
    UnionDSU(head, len, 5, 6);
    PrintfDSU(head, len);
    UnionDSU(head, len, 6, 3);
    PrintfDSU(head, len);
    UnionDSU(head, len, 9, 1);
    PrintfDSU(head, len);
    UnionDSU(head, len, 8, 6);
    PrintfDSU(head, len);
    UnionDSU(head, len, 0, 7);
    PrintfDSU(head, len);
    UnionDSU(head, len, 7, 0);
    PrintfDSU(head, len);
    UnionDSU(head, len, 0, 9);
    PrintfDSU(head, len);
    PrintfLinkedNumDSU(head, len);
    DestoryDSU(head);
    return 0;
}

算法模型 (Algorithmic Model)

位运算

bithacks

大小写转换

/* 转化成小写 */
(c | ' ')

/* 转化成大写 */
(c & ' ')

/* 大小写互换 */
(c ^ ' ')

消除二进制中的最后一个1

n & (n - 1)

异或特性

/* 一个数与自己异或等于0 */
n ^ n == 0

/* 一个数与0异或等于自己 */
n ^ 0 == n

数学类算法

阶乘后的0的个数

思路
计算可以提供5的因子个数。如5的倍数可以提供第一个1个因子的5,25的倍数可以提供第二个因子的5,依次类推

代码实现

long long TrailingZeroes(long long n)
{
    long long res = 0;
    long long divisor = 5;
    while (divisor <= n) {
        res += n / divisor;
        divisor *= 5;
    }
    
    return res;
 }

质数

思路
欧几里德算法求最大公约数,公约数为1的则互质。

代码实现

int gcd(int x, int y)
{
    int t;
    while(y % x != 0) {
        t = x;
        x = y % x;
        y = t;
    }
    return x;
}

素数

定义
一个数如果只能被1和它本身整除,1除外

思路
如果当前数是素数,则其之后的倍数都不是,如 3是素数,则 3 + 3, 3 + 3 + 3 ... 都不是。而且一个数在其平方根前后相乘是对称的,如6=23; 6=32

代码实现

int CountPrimes(int n)
{
    bool isPrime[n + 1];
    
    for (int i = 0; i <= n; i++) {
        isPrime[i] = true;
    }
    for (int i = 2; i * i <= n; i++) {
        if (isPrime[i]) {
            for (int j = i * i; j <= n; j += i) {
                isPrime[j] = false;
            }
        }
    }
    
    int count = 0;
    for (int i  = 2; i <= n; i++) {
        if (isPrime[i]) {
            count++;
        }
    }
    return count;
}

int IsPrimes(int n)
{
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) {
            return false;
        }
    }
    
    return true;
}

幂函数

思路
利用幂运算的性质

代码实现

unsigned long long mypow(unsigned long long a, unsigned long long k)
{
    if (k == 0) {
        return 1;
    }
    
    if (k % 2 == 1) {
        return (a * mypow(a, k - 1));
    }
    
    unsigned long long sub = mypow(a, k / 2);
    return (sub * sub);
}

两数相除

思路
采用逐次逼近法
如 11 / 3
3 < 11
3 * 2 = 6 < 11
6 * 2 = 12 > 11 停止,得到一个2接着用11 - 6 = 5 逐次逼近
3 < 5
3 * 2 > 5 停止,得到一个1接着用5 - 3 = 2 逐次逼近
3 > 2 停止
最终结果为 3

代码实现

int mydiv(int a, int b)
{
    if (a < b) {
        return 0;
    }
    
    int ta = a;
    int tb = b;
    while (tb <= ta) {
        tb = tb * 2;
    }
    
    return (tb / 2 / b) + mydiv(ta - tb / 2, b);
}

小而美的算法技巧

前缀和

思路
利用已经求出的结果,推导未知结果,从而减少计算量

例子

差分数组

思路
构造差分数组是为了让前后的数据产生关系,一旦要操作某个区间的时候,只要操作边界两个位置就能对整个区间产生影响,从而减少计算量

例子

路径和

思路

例子

双指针

左右指针

思路
两个指针相向或相背而行

例子
有序数组中的查找某个值的位置

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

int binarySearch(int *a, int aLen, int target)
{
    int left = 0, right = aLen - 1;
    int mid = (left + right) / 2;

    while (left <= right) {
        mid = (left + right) / 2;
        
        if (a[mid] == target) {
            return mid;
        } else if (a[mid] < target) {
            left = mid + 1;
        }  else if (a[mid] > target) {
            right = mid - 1;
        }
    }
    
    return  -1;
}

int main(void)
{
    int a[10] = {-2, 1, 3, 5, 7, 8, 1000, 10000, 10001, 1000000};
    printf("binarySearch(a, %d)=%d\r\n", 1000000, binarySearch(a, sizeof(a) / sizeof(int), 1000000));

    return 0;
}

快慢指针

两个指针相向或相背而行,一快一慢

例子
删除有序数组中的重复项

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

void removeDuplicates(int *a, int aLen, int *outLen)
{
    int slow = 0, fast = slow + 1;
    
    for (fast = slow + 1; fast < aLen; fast++) {
        if (a[slow] != a[fast]) {
            a[++slow] = a[fast];
        }
    }
    
    *outLen = slow + 1;
}

int main(void)
{
    int a[10] = {-2, 1, 3, 5, 7, 8, 8, 8, 9, 9};
    int resLen =0;
    removeDuplicates(a, sizeof(a) / sizeof(int), &resLen);
    printf("ResLen=%d\r\n", resLen);

    return 0;
}

滑动窗口

两个指针相向而行,但要保证窗口里的数据规律不变。如果因为窗口的变化导致数据规律变化了,则需缩小窗口,达到规律

例子
给你一个字符串S,一个字符串T,请在S中找出所有字母的最小子串

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

int minWindow(char *s, char *t)
{
    int sLen = strlen(s);
    int tLen = strlen(t);
    int need[256] = {0};
    int window[256] = {0};
    int needCnt = 0;
    int windowCnt = 0;

    for (int i = 0; i < tLen; i++) {
        if (need[t[i]] == 0) {
            needCnt++;
        }
        need[t[i]]++;   
    }
    
    int left = 0, right = 0;
    int minLen = sLen;
    int pos = -1;
    while (right < sLen) {
        if (need[s[right]] != 0) {
            window[s[right]]++;
            if (window[s[right]] == need[s[right]]) {
                windowCnt++;
            }
        }
        right++;
    
        while (windowCnt == needCnt) {
            if ((right - left) < minLen) {
                minLen = right - left;
                pos = left;
            }
            if (need[s[left]] != 0) {
                window[s[left]]--;
                if (window[s[left]] != need[s[left]]) {
                    windowCnt--;
                }
            }
            left++;
        }
    }
    
    return pos;
}

int main(void)
{
    char *s = "ADOBECODEBANC";
    char *t = "ABC";

    printf("Res=%d\r\n", minWindow(s, t));
    
    return 0;
}

常见算法题

正则表达式匹配

递归解法

bool match(char* str, char* pattern ) {
    if (str[0] == '\0' || pattern[0] == '\0') {
        if (str[0] == '\0' && pattern[0] == '\0') {
            return true;
        } else if (str[0] != '\0' && pattern[0] == '\0') {
            return false;
        } else if (str[0] == '\0' && pattern[0] != '\0') {
            if (pattern[1] == '*') {
                return match(str, pattern + 2);
            } else {
                return false;
            }
        }
    }
    
    if (pattern[1] == '*') {
        if (str[0] == pattern[0] || pattern[0] == '.') {
            return match(str + 1, pattern) || match(str, pattern + 2);
        } else {
            return match(str, pattern + 2);
        }
    } else {
        if (str[0] == pattern[0] || pattern[0] == '.') {
            return match(str + 1, pattern + 1);
        } else {
            return false;
        }
    }
}

动态规划解法


Dijkstra算法

struct queueNode {
    int cur;
    int dist;
};
struct queue {
    struct queueNode *buf;
    int maxLen;
    int start;
    int end;
};

struct queue *CreateQueue(int maxLen)
{
    struct queue *q = malloc(sizeof(struct queue));

    q->buf = malloc(maxLen * sizeof(struct queueNode));
    q->maxLen = maxLen;
    q->start = 0;
    q->end = 0;

    return q;
}

bool QueueIsEmpty(struct queue *q)
{
    return q->start == q->end;
}

void QueuePush(struct queue *q, int cur, int dist)
{
#if 0
    struct queueNode node;
    int end = (q->end - 1 < 0) ? (q->maxLen - 1) : (q->end - 1 < 0);
    int start = (q->start - 1 < 0) ? (q->maxLen - 1) : (q->start - 1 < 0);
    node.cur = cur;
    node.dist = dist;
    q->buf[q->end] = node;
    while (end != start && q->buf[end].dist > dist) {
        int nextEnd = ((end + 1) >= q->maxLen) ? (0) : (end + 1);
        q->buf[nextEnd] = q->buf[end];
        q->buf[end] = node;
        end--;
        if (end < 0) {
            end = q->maxLen - 1;
        }
    }
#endif
#if 1
    q->buf[q->end].cur = cur;
    q->buf[q->end].dist = dist;
#endif
    q->end = q->end + 1;
    if (q->end >= q->maxLen) {
        q->end = 0;
    }
}

struct queueNode QueuePop(struct queue *q)
{
    struct queueNode res = q->buf[q->start];
    q->start = q->start + 1;
    if (q->start >= q->maxLen) {
        q->start = 0;
    }

    return res;
}

int networkDelayTime(int** times, int timesSize, int* timesColSize, int n, int k){
    int graphColSize = n + 1;
    int **graph = malloc(graphColSize * sizeof(int *));

    for (int i = 0; i < graphColSize; i++) {
        graph[i] = malloc(graphColSize * sizeof(int));
        for (int j = 0; j < graphColSize; j++) {
            graph[i][j] = -1;
        }
    }

    for (int i = 0; i < timesSize; i++) {
        graph[times[i][0]][times[i][1]] = times[i][2];
    }

    int distTo[graphColSize];
    for (int i = 0; i < graphColSize; i++) {
        distTo[i] = INT_MAX;
    }
    distTo[k] = 0;

    struct queue *q = CreateQueue(1000);
    QueuePush(q, k, 0);

    while (!QueueIsEmpty(q)) {
        struct queueNode node = QueuePop(q);
        if (distTo[node.cur] < node.dist) {
            continue;
        }
        for (int next = 1; next < graphColSize; next++) {
            if (graph[node.cur][next] < 0) {
                continue;
            }
            int distToNext = distTo[node.cur] + graph[node.cur][next];
            if (distTo[next] > distToNext) {
                distTo[next] = distToNext;
                QueuePush(q, next, distToNext);
            }
        }
    }

    int max = 0;
    for (int i = 1; i < graphColSize; i++) {
        if (distTo[i] == INT_MAX) {
            return -1;
        }
        if (max < distTo[i]) {
            max = distTo[i];
        }
    }

    return max;
}
posted @ 2023-02-11 21:19  未知电子  阅读(21)  评论(0编辑  收藏  举报