跳转至

算法题常用模板

单链表

// C语言种typedef只有在结构体声明后才生效,因此结构体内还得写struct
typedef struct Node{
    int data;
    struct Node* next;
}Node, *LinkList;
//typedef 的整体结构可以理解为:typedef + 原有类型声明 + 类型别名;
// Node:结点类型,等价于 struct Node
// LinkList:结点指针类型,等价于 Node *,通常用作链表头指针。其中*和Node放一块更好理解

//malloc申请结点
Node *p = (Node *)malloc(sizeof(Node)); //申请一个结点大小的内存空间。如果里面写成Node*就是一个指针的大小了
//malloc申请单链表
LinkList L = (LinkList)malloc(sizeof(Node));
    //初始化带头节点的单链表,malloc是可能失败的,因此需要if一下
if(L != NULL) L -> next = NULL;
//free结点
free(p);
//free链表时需要依次free链表中的结点(不释放头结点)
Node *p; //这里不需要新申请空间,因为是用来释放空间的,指向所要释放的结点
while(L -> next != NULL){
    p = L -> next;
    L -> next = p -> next;
    free(p);
}
//释放头结点
Node *p;
while(L != NULL){
    p = L;
    L = L -> next;
    free(p);
}

单链表寻找中间节点

快慢指针,慢指针走一步,快指针走两步,快指针走到尾了,慢指针所指即为中间节点

NODE *p = h, *q = h;
while(q -> next != NULL){
    p = p -> next;
    q = q -> next;
    if(q -> next != NULL) q = q -> next;
}

未知长度单链表找“倒数第 \(k\) 个节点”

双指针,让其中一个先跑k个另一个再出发,先出发的到终点了后出发的指针所指即为所求

NODE *fast = h, *slow = h;
while(k > 0 && fast != NULL){
    fast = fast -> next;
    k --;
}
// 链表长度不足k
if(k != 0 || fast == NULL) return 0;
while(fast != NULL){
    fast = fast -> next;
    slow = slow -> next;
}
//此时slow所指即为所求

注意事项

char data:单个字符,使用 %c。

char data[10]:字符数组,存储以 \0 结尾的字符串时使用 %s。

T.data 与 T->data:结构体变量用 ., 结构体指针用 ->。

快排

//标准填坑法,保证一趟排序可确定枢轴最终位置
// 一趟划分,返回枢轴的最终位置
int partition(int a[], int l, int r){
    int x = a[l];//第一个为枢轴,挖坑
    while(l < r){
        //找第一个小于x的
        while(l < r && a[r] >= x) r --;
        a[l] = a[r];//填左坑

        //找第一个大于x的
        while(l < r && a[l] <= x) l ++;
        a[r] = a[l];//填右坑
    }
    //剩出来的坑即为枢轴最终位置
    a[l] = x;
    return l;
}

void quick_sort(int a[], int l, int r){
    if(l >= r) return;

    int p = partition(a, l, r);

    quick_sort(a, l, p - 1);
    quick_sort(a, p + 1, r);
}

依据一趟确定一个数的最终位置,快排的思想可以在o(n)的情况下求出无序数组中第K大或第K小的元素这个算法就叫 快速选择(Quickselect)。

int partition(int a[], int l, int r){
    int x = a[l];
    while(l < r){
        while(l < r && a[r] >= x) r --;
        a[l] = a[r];
        while(l < r && a[l] <= x) l ++;
        a[r] = a[l];
    }
    a[l] = x;
    return l;
}

int find_k(int a[], int l, int r, int k){
    if(l >= r) return a[l];
    int p = partition(a, l, r);
    //以第k小为例
    if(p == k - 1) return a[p];
    else if(p > k - 1) return find_k(a, l, p - 1, k);
    else return find_k(a, p + 1, r, k);
}