Verknüpfte Liste (C-Implementierung)

Rezension für den persönlichen Gebrauch, keine Analyse.

Am Beispiel einer einseitig verknüpften Liste mit Sentinel-Knoten besteht das Ziel darin, die folgende Methode zu implementieren (teilweise wird auf den <list>-Container von C++ STL verwiesen):

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

typedef int ValType;

typedef struct node {
    ValType val;
    struct node *next;
} Node, List;

List* init(void); // 初始化链表
bool empty(List* head); // 判断链表为空
void clear(List* head); // 清空链表
void destroy(List* head); // 销毁链表
int size(List* head); // 链表大小
bool traverse(List* head); // 遍历链表

void pushFront(List* head, ValType val); // 头插法
void pushBack(List* head, ValType val); // 尾插法
ValType popFront(List* head); // 头出法
ValType popBack(List* head); // 尾出法
ValType front(List* head); // 头部元素
ValType back(List* head); // 尾部元素

bool insert(List* head, int n, ValType val); // 指定位置插入元素
ValType get(List* head, int n); // 获取指定位置元素
int match(List* head, ValType val); // 寻找匹配的元素
ValType delete(List* head, int n); // 删除指定位置元素
ValType deleteReverse(List *head, int n); // 反序删除指定位置元素

bool resize(List* head, int n); // 重新设置链表大小
bool reverse(List* head); // 翻转链表
bool sort(List* head); // 链表排序
bool unique(List* head); // 删除有序链表中的重复元素
List* splice(List* dest, List* src); // 拼接两个链表
List* merge(List* src1, List* src2); // 合并两个有序链表

Die spezifische Implementierung jeder Methode ist wie folgt:

Node* newNode(ValType val);
void quickSort(ValType arr[], int left, int right);
 
Node* newNode(ValType val) {
    Node* node = (Node*)malloc(sizeof(Node));
    node->val = val;
    node->next = NULL;
    return node;
}
 
List* init(void) {
    List* head = newNode(-1);
    return head;
}

bool empty(List* head) {
    if (head->next == NULL) return true;
    return false;
}

// 保留头节点
void clear(List* head) {
    while (head->next) {
        List* curr = head->next;
        head->next = curr->next;
        free(curr);
    }
}

// 指针置空
void destroy(List* head) {
    List* curr = head;
    while (curr) {
        head = head->next;
        free(curr);
        curr = head;
    }
}
 
int size(List* head) {
    int cnt = 0;
    for (Node* curr = head->next; curr; curr = curr->next) ++cnt;
    return cnt;
}
 
bool traverse(List* head) {
    if (empty(head)) return false;
    for (Node* curr = head->next; curr; curr = curr->next) {
        printf("%d ", curr->val);
    }
    printf("\n");
    return true;
}

void pushFront(List* head, ValType val) {
    Node* curr = newNode(val);
    curr->next = head->next;
    head->next = curr;
}
 
// O(n)
void pushBack(List* head, ValType val) {
    Node* tail = head;
    while (tail->next) tail = tail->next;
    tail->next = newNode(val);
}
 
ValType popFront(List* head) {
    if (empty(head)) return -1;
    Node* curr = head->next;
    head->next = curr->next;
    ValType val = curr->val;
    free(curr);
    return val;
}

// O(n)
ValType popBack(List* head) {
    if (empty(head)) return -1;
    Node* prev = head;
    while (prev->next->next) prev = prev->next;
    ValType val = prev->next->val;
    free(prev->next);
    prev->next = NULL;
    return val;
}
 
ValType front(List* head) {
    if (empty(head)) return -1;
    return head->next->val;
}

// O(n)
ValType back(List* head) {
    if (empty(head)) return -1;
    Node* tail = head;
    while (tail->next) tail = tail->next;
    return tail->val;
}

// 遍历到满足条件的前一个节点
bool insert(List* head, int n, ValType val) {
    if (empty(head) || n < 1) return false;
    for (Node* prev = head; prev->next; prev = prev->next) {
        --n;
        if (n == 0) {
            Node* new = newNode(val);
            new->next = prev->next;
            prev->next = new;
            return true;
        }
    } return false;
}

ValType get(List* head, int n) {
    if (empty(head) || n < 1) return -1;
    for (Node* curr = head->next; curr->next; curr = curr->next) {
        --n;
        if (n == 0) {
            return curr->val;
        }
    } return -1;
}

int match(List* head, ValType val) {
    if (empty(head)) return -1;
    int cnt = 0;
    for (Node* curr = head->next; curr->next; curr = curr->next) {
        ++cnt;
        if (curr->val == val) return cnt;
    } return -1;
}

// 遍历到满足条件的前一个节点
ValType delete(List* head, int n) {
    if (empty(head) || n < 1) return -1;
    for (Node* prev = head; prev->next; prev = prev->next) {
        --n;
        if (n == 0) {
            Node* del = prev->next;
            prev->next = del->next;
            ValType val = del->val;
            free(del);
            return val;
        }
    } return -1;
}

// 双指针法
ValType deleteReverse(List *head, int n) {
    if (empty(head) || n < 1) return -1;
    Node* fast = head->next;
    for (int i = n - 1; i > 0; --i) {
        if (fast->next == NULL) return -1;
        fast = fast->next;
    }
    Node* slow = head;
    while (fast->next) {
        fast = fast->next;
        slow = slow->next;
    }
    Node* curr = slow->next;
    slow->next = curr->next;
    ValType val = curr->val;
    free(curr);
    return val;
}

// 遍历到满足条件的前一个节点
bool resize(List* head, int n) {
    if (empty(head) || n < 1) return false;
    for (Node* prev = head; prev->next; prev = prev->next) {
        --n;
        if (n == 0) {
            clear(prev->next);
            return true;
        }
    } return false;
}

// 三指针迭代法
bool reverse(List* head) {
    if (empty(head) || empty(head->next)) return false;
    Node *prev = NULL, *curr = head->next;
    while (curr) {
        Node* next = curr->next;
        curr->next = prev;
        prev = curr, curr = next;
    }
    head->next = prev;
    return true;
}

// 传入数组使用快排
bool sort(List* head) {
    if (empty(head) || empty(head->next)) return false;
    int arrSize = size(head);
    ValType* arr = (ValType*)malloc(sizeof(ValType) * arrSize);
    Node* curr = head->next;
    for (int i = 0; i < arrSize; ++i) {
        arr[i] = curr->val;
        curr = curr->next;
    }
    quickSort(arr, 0, arrSize - 1);
    curr = head->next;
    for (int i = 0; i < arrSize; ++i) {
        curr->val = arr[i];
        curr = curr->next;
    }
    free(arr);
    return true;
}

// 遍历到重复值出现的前一个节点
bool unique(List* head) {
    if (empty(head) || empty(head->next)) return false;
    Node* prev = head->next;
    while (prev->next->next) {
        if (prev->val > prev->next->val) {
            return false;
        } else if (prev->val == prev->next->val) {
            Node* curr = prev->next;
            prev->next = curr->next;
            free(curr);
        } else {
            prev = prev->next;
        }
    } return true;
}

List* splice(List* dest, List* src) {
    if (empty(dest)) return src;
    if (empty(src)) return dest;
    Node* tail = dest;
    while (tail->next) tail = tail->next;
    tail->next = src->next;
    return dest;
}

List* merge(List* src1, List* src2) {
    if (empty(src1)) return src2;
    if (empty(src2)) return src1;
    sort(src1), sort(src2);
    List* dest = init();
    Node *curr1 = src1->next, *curr2 = src2->next, *tail = dest;
    while (curr1 && curr2) {
        if (curr1->val < curr2->val) {
            tail->next = curr1;
            curr1 = curr1->next;
            tail = tail->next;
        } else {
            tail->next = curr2;
            curr2 = curr2->next;
            tail = tail->next;
        }
    }
    // 将剩余部分直接连接
    if (curr1) tail->next = curr1;
    if (curr2) tail->next = curr2;
    src1->next = NULL, src2->next = NULL;
    return dest;
}

void quickSort(int arr[], int left, int right) {
    if (left >= right) return;
    srand(time(NULL));
    int idx = rand() % (left - right) + left;
    int flag = arr[idx], head = left - 1, tail = right + 1;
    while (head < tail) {
        do head++; while(arr[head] < flag);
        do tail--; while(arr[tail] > flag);
        if (head < tail) {
            int tmp = arr[head];
            arr[head] = arr[tail];
            arr[tail] = tmp;
        }
    }
    quickSort(arr, left, tail);
    quickSort(arr, tail + 1, right);
}

Testfall:

void test1();
void test2();

void test1() {
    List* list = init();
    pushBack(list, 4);
    pushBack(list, 5);
    pushBack(list, 6);
    pushFront(list, 3);
    pushFront(list, 2);
    pushFront(list, 1);
    traverse(list);

    printf("%d %d %d\n", size(list), front(list), back(list));
    printf("%d %d %d\n", get(list, 3), match(list, 5), match(list, 10));

    insert(list, 3, 0);
    traverse(list);
    deleteReverse(list, 5);
    traverse(list);
    delete(list, 2);
    traverse(list);

    printf("%d %d\n", popFront(list), popBack(list));
    traverse(list);

    pushFront(list, 2);
    pushBack(list, 6);
    pushBack(list, 7);
    traverse(list);
    resize(list, 4);
    traverse(list);

    reverse(list);
    traverse(list);

    clear(list);
    printf("%d\n", size(list));

    destroy(list);
    printf("\n");
    return;
}

void test2() {
    List* list = init();
    pushFront(list, 2);
    pushFront(list, 4);
    pushFront(list, 9);
    pushFront(list, 11);
    pushFront(list, 2);
    pushFront(list, 10);
    pushFront(list, 2);
    pushFront(list, 8);
    pushFront(list, 1);
    pushFront(list, 12);
    pushFront(list, 3);
    pushFront(list, 2);
    pushFront(list, 11);
    pushFront(list, 14);
    pushFront(list, 4);
    pushFront(list, 2);
    traverse(list);

    sort(list);
    traverse(list);

    unique(list);
    traverse(list);

    List* list2 = init();
    pushFront(list2, 9);
    pushFront(list2, 7);
    pushFront(list2, 7);
    pushFront(list2, 3);
    pushFront(list2, 2);
    traverse(list2);

    List* list3 = merge(list, list2);
    traverse(list3);
}

Supongo que te gusta

Origin blog.csdn.net/annesede/article/details/134173604
Recomendado
Clasificación