小練習 - 單鏈表冒泡排序,交換指針域

鏈表的排序,好的做法是交換指針域。鏈表節點的數據域可能比較大,交換數據域可能會涉及拷貝過多的內存,影響性能。鏈表是鏈式存儲,無法隨機訪問(base_addr + offset), 所以比較適合的辦法是用比較兩兩相鄰節點的冒泡排序法。當然還有一個辦法就是,把所有的鏈表地址存到一個數組裏,排序後重新遍歷設置所有指針域,這個就多了兩次遍歷,也可以。下面是交換指針域的一個單鏈表冒泡排序的例子:

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

struct Node {
    int data;
    struct Node *next;
};

struct Node *listHead = NULL;
struct Node *listTail = NULL;

/* 交換指針域,冒泡排序單鏈表 */
void sortList()
{
    struct Node *cur, *prev, *tmp, *last;
    cur = listHead;
    prev = listHead;
    last = NULL;
    int i = 0, j = 0;

    while (cur != last) {
        i = 0;
        while (cur != NULL && cur->next != last) {
            if (cur->data > cur->next->data) {
                /* cur, cur->next 交換位置 */
                tmp = cur->next;
                cur->next = cur->next->next;
                tmp->next = cur;
                if (i > 0)
                    prev->next = tmp;  /* 第一次交換: prev == cur */

                /* 移動 prev, cur 節點,這裏cur已經是下一個 */
                prev = tmp;

                /* 維護頭結點 */
                if (i == 0)
                    listHead = prev;
            } else {
                /* 節點不交換位置 */
                prev = cur;
                cur = cur->next;
            }
            i++;
        }

        /* 維護尾節點 */
        if (j++ == 0) {
            listTail = cur;
            listTail->next = NULL;
        }

        last = cur;
        cur = listHead;
        prev = listHead;
    }
}

void initList()
{
    size_t i;
    struct Node *node;
    int nums[] = {8, 7, 6, 5, 0, 2, 3, 9, 4, 1};
    for (i = 0; i < sizeof(nums) / sizeof(int); i++) {
        node = (struct Node*)malloc(sizeof(struct Node));
        node->data = nums[i];
        node->next = NULL;
        if (listHead == NULL) {
            listHead = node;
        }
        if (listTail == NULL) {
            listTail = node;
        } else {
            listTail->next = node;
            listTail = node;
        }
    }
}

void printList()
{
    struct Node *node;
    node = listHead;
    while (node != NULL) {
        printf("%d ", node->data);
        node = node->next;
    }
    printf("\n");
}

int main()
{
    initList();
    printf("before: ");
    printList();
    sortList();
    printf("after : ");
    printList();
    printf("head %d, tail %d\n", listHead->data, listTail->data);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章