contributed by < Ken-LuWeiRu >
linux2024在編譯過程中出現以下訊息
$git commit -m "Test q1t1" 
Following files need to be cleaned up:
original_q1t1.c
queue.c
original_q1t1.c:124:11: style: Checking if unsigned expression 'n' is less than zero. [unsignedLessThanZero]
    if (n <= 0)
          ^
original_q1t1.c:78:25: style: Local variable 'n' shadows outer variable [shadowVariable]
                node_t *n = p;
                        ^
original_q1t1.c:59:9: note: Shadowed declaration
    int n = list_length(list);
        ^
original_q1t1.c:78:25: note: Shadow variable
                node_t *n = p;
                        ^
      重寫 shuffle 和 quick_sort 函數
void shuffle(size_t *array, size_t n)
{
    // if (n <= 0) 移除這行,因為 size_t 類型的 n 永遠不會小於零
    for (size_t i = 0; i < n - 1; i++) {
        size_t j = i + rand() / (RAND_MAX / (n - i) + 1);
        size_t t = array[j];
        array[j] = array[i];
        array[i] = t;
    }
}
void quick_sort(node_t **list)
{
    int length = list_length(list); // 更改這裡的變量名,避免與下方的 node_t 變量重名
    int value;
    int i = 0;
    int max_level = 2 * length; // 這裡使用修改後的變量名
    node_t *begin[max_level], *end[max_level];
    node_t *result = NULL, *left = NULL, *right = NULL;
    begin[0] = *list;
    end[0] = list_tail(list);
    while (i >= 0) {
        node_t *L = begin[i], *R = end[i];
        if (L != R) {
            node_t *pivot = L;
            value = pivot->value;
            node_t *p = pivot->next;
            pivot->next = NULL;
            while (p) {
                node_t *node_ptr = p; // 修改變量名稱,避免重名
                p = p->next;
                list_add(node_ptr->value > value ? &right : &left, node_ptr); // 這裡也使用修改後的變量名
            }
            begin[i] = left;
            end[i] = list_tail(&left);
            begin[i + 1] = pivot;
            end[i + 1] = pivot;
            begin[i + 2] = right;
            end[i + 2] = list_tail(&right);
            left = right = NULL;
            i += 2;
        } else {
            if (L)
                list_add(&result, L);
            i--;
        }
    }
    *list = result;
}
      測試
int main(int argc, char **argv)
{
    node_t *list = NULL;
    const int sizes[] = {10000, 50000, 100000};  // 定義不同大小的測試案例
    const int num_sizes =
        sizeof(sizes) / sizeof(sizes[0]);  // 計算測試案例的數量
    double elapsed_times[num_sizes];  // 儲存每個測試案例的執行時間
    for (int s = 0; s < num_sizes; ++s) {
        size_t count = sizes[s];
        int *test_arr = malloc(sizeof(int) * count);
        // 產生隨機數據
        for (int i = 0; i < count; ++i)
            test_arr[i] = i;
        shuffle(test_arr, count);
        // 構建鏈表
        for (size_t i = 0; i < count; ++i)
            list = list_construct(list, test_arr[i]);
        clock_t start = clock();  // 開始計時
        quick_sort(&list);        // 執行快速排序
        clock_t end = clock();    // 結束計時
        elapsed_times[s] =
            (double) (end - start) / CLOCKS_PER_SEC;  // 計算經過時間
        assert(list_is_ordered(list));  // 驗證列表是否已排序
        list_free(&list);               // 釋放列表記憶體
        free(test_arr);                 // 釋放測試陣列記憶體
    }
    // 輸出每個測試案例的執行時間
    for (int i = 0; i < num_sizes; ++i) {
        printf("Size %d: %f seconds\n", sizes[i], elapsed_times[i]);
    }
    return 0;
}
      輸出
Size 10000: 0.001226 seconds
Size 50000: 0.008770 seconds
Size 100000: 0.019222 seconds
      採用 list.h 進行重構
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>  // 加入 time.h 以使用 clock()
#include "list.h"  // 匯入 Linux 風格的鏈結串列定義
typedef struct __node {
    struct list_head list;  // 用於雙向鏈結串列的節點
    long value;             // 節點存儲的數值
} node_t;
int list_length(struct list_head *head)
{
    struct list_head *pos;
    int n = 0;
    list_for_each (pos, head) {
        ++n;
    }
    return n;
}
node_t *list_construct(long n)
{
    node_t *node = malloc(sizeof(node_t));
    INIT_LIST_HEAD(&node->list);  // 初始化 list_head 結構
    node->value = n;
    return node;
}
void list_free(struct list_head *head)
{
    struct list_head *pos, *q;
    list_for_each_safe (pos, q, head) {
        // 確保 pos 不是指向 list_head 自身,否則將導致 list_entry
        // 返回不正確的指針
        if (pos != head) {
            node_t *tmp_node = list_entry(pos, node_t, list);
            list_del(pos);
            free(tmp_node);
        }
    }
}
void quick_sort(struct list_head *head)
{
    if (list_empty(head) || list_is_singular(head)) {
        return;
    }
    struct list_head *pivot = head->next;
    struct list_head sorted;
    INIT_LIST_HEAD(&sorted);
    struct list_head *current = NULL, *temp = NULL;
    LIST_HEAD(less);
    LIST_HEAD(greater);
    list_for_each_safe (current, temp, head) {
        if (current != pivot) {  // 確保當前節點不是 pivot
            node_t *node = list_entry(current, node_t, list);
            node_t *pivot_node = list_entry(pivot, node_t, list);
            if (node->value < pivot_node->value) {
                list_move_tail(current, &less);
            } else {
                list_move_tail(current, &greater);
            }
        }
    }
    quick_sort(&less);
    quick_sort(&greater);
    list_splice(&less, head);
    list_splice_tail(&sorted, head);
    list_splice_tail(&greater, head);
}
static bool list_is_ordered(struct list_head *head)
{
    if (list_empty(head) || list_is_singular(head)) {
        return true;
    }
    node_t *current_node = NULL, *next_node = NULL;
    struct list_head *node;
    list_for_each (node, head) {
        if (node != head) {  // 確保節點不是 list_head 自身
            current_node = list_entry(node, node_t, list);
            if (node->next != head) {  // 確保下一個節點不是 list_head 自身
                next_node = list_entry(node->next, node_t, list);
                if (current_node->value > next_node->value) {
                    return false;
                }
            }
        }
    }
    return true;
}
void shuffle(int *array, size_t n)
{
    // if (n <= 0)
    //     return;
    // 移除這行,因為 size_t 類型的 n 永遠不會小於零
    for (size_t i = 0; i < n - 1; i++) {
        size_t j = i + rand() / (RAND_MAX / (n - i) + 1);
        int t = array[j];
        array[j] = array[i];
        array[i] = t;
    }
}
int main(int argc, char **argv)
{
    struct list_head list;
    INIT_LIST_HEAD(&list);
    const int sizes[] = {10000, 50000, 100000};
    const int num_sizes = sizeof(sizes) / sizeof(sizes[0]);
    double elapsed_times[num_sizes];
    for (int s = 0; s < num_sizes; ++s) {
        size_t count = sizes[s];
        int *test_arr = malloc(sizeof(int) * count);
        for (int i = 0; i < count; ++i) {
            test_arr[i] = rand() % count;
        }
        shuffle(test_arr, count);
        for (size_t i = 0; i < count; ++i) {
            node_t *new_node = list_construct(test_arr[i]);  // 使用构造函数
            list_add_tail(&(new_node->list), &list);
        }
        clock_t start = clock();
        quick_sort(&list);
        clock_t end = clock();
        elapsed_times[s] = (double) (end - start) / CLOCKS_PER_SEC;
        assert(list_is_ordered(&list));
        list_free(&list);  // 使用自定义的函数清理内存
        free(test_arr);
    }
    for (int i = 0; i < num_sizes; ++i) {
        printf("Size %d: %f seconds\n", sizes[i], elapsed_times[i]);
    }
    return 0;
}
      輸出
Size 10000: 0.001075 seconds
Size 50000: 0.006973 seconds
Size 100000: 0.015436 seconds
      我想將 timsort 加進 qtest.c 中
在 qtest.c 加入
int compare(void *priv, const struct list_head *a, const struct list_head *b)
{
    const element_t *elem_a = list_entry(a, element_t, list);
    const element_t *elem_b = list_entry(b, element_t, list);
    return strcmp(elem_a->value, elem_b->value);
}
static bool do_timsort(int argc, char *argv[])
{
    if (argc != 1) {
        report(1, "%s takes no arguments", argv[0]);
        return false;
    }
    if (!current || !current->q) {
        report(3, "Warning: Calling timsort on null or empty queue");
        return false;
    }
    if (exception_setup(true)) {
        timsort(NULL, current->q, compare);
    }
    exception_cancel();
    return q_show(0) && !error_check();
}
      並且在 static void console_init() 中加入
    ADD_COMMAND(timsort, "Sort queue using timsort algorithm", "");
      現在就可以在執行 qtest 後輸入 timsort 來排序
https://port70.net/~nsz/c/c11/n1570.html#6.2.5
contributed by < Ken-LuWeiRu >
May 29, 2024contributed by < weihsinyeh >
Apr 28, 2024contributed by < Ken-LuWeiRu >
Apr 2, 2024$ gcc -vUsing built-in specs.COLLECT_GCC=gccCOLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapperOFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsaOFFLOAD_TARGET_DEFAULT=1Target: x86_64-linux-gnuConfigured with: ../src/configure -v –with-pkgversion='Ubuntu 11.4.0-1ubuntu1~22.04' –with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs –enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 –prefix=/usr –with-gcc-major-version-only –program-suffix=-11 –program-prefix=x86_64-linux-gnu- –enable-shared –enable-linker-build-id –libexecdir=/usr/lib –without-included-gettext –enable-threads=posix –libdir=/usr/lib –enable-nls –enable-bootstrap –enable-clocale=gnu –enable-libstdcxx-debug –enable-libstdcxx-time=yes –with-default-libstdcxx-abi=new –enable-gnu-unique-object –disable-vtable-verify –enable-plugin –enable-default-pie –with-system-zlib –enable-libphobos-checking=release –with-target-system-zlib=auto –enable-objc-gc=auto –enable-multiarch –disable-werror –enable-cet –with-arch-32=i686 –with-abi=m64 –with-multilib-list=m32,m64,mx32 –enable-multilib –with-tune=generic –enable-offload-targets=nvptx-none=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-gcn/usr –without-cuda-driver –enable-checking=release –build=x86_64-linux-gnu –host=x86_64-linux-gnu –target=x86_64-linux-gnu –with-build-config=bootstrap-lto-lean –enable-link-serialization=2Thread model: posixSupported LTO compression algorithms: zlib zstdgcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)
Mar 26, 2024or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up