單鏈表排序

單鏈表排序
初始化

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

//節點結構
struct node
{
    int val;
    struct node * next;
};
typedef struct node node, * list;

//打印函數
void printList(list mylist);
//排序函數
//插入排序
void insertSort(list mylist);
//冒泡排序
void bubbleSort(list mylist);
//簡單選擇
void selectSort(list mylist);
//快速排序
void quickSort(list mylist);

int main(void)
{
    int arr[] = {5, 1, 7, 4, 2, 9, 6, 3, 8};
    //程序都是針對有頭結點的單向鏈表
    list mylist = (list)malloc(sizeof(node));
    mylist -> val = 0;
    mylist -> next = NULL;
    int len = sizeof(arr) / sizeof(arr[0]);
    int i = 0;
    node * cur = mylist;
    while(i < len)
    {
        node * newNode = (node *)malloc(sizeof(node));
        newNode -> val = arr[i];
        newNode -> next = NULL;
        cur -> next = newNode;
        cur = cur -> next;
        i ++;
    }
    //insertSort(mylist);
    //bubbleSort(mylist);
    //selectSort(mylist);
    quickSort(mylist);
    printList(mylist);

    return 0;
}

void printList(list mylist)
{
    node * cur = mylist -> next;
    while(cur != NULL)
    {
        printf("%d ", cur -> val);
        cur = cur -> next;
    }
    printf("\n");
}

---------------------

一、交換節點的單鏈表排序:
交換節點的情況比較複雜,所以我只是寫了比較簡單的三個。

1 、插入排序:

//=============插入排序====================
void insertSort(list mylist)
{
    if((mylist -> next == NULL) || (mylist -> next -> next == NULL))
    {   
        return;
    }   

    node * head, * p1, * prep1, * p2, * prep2, * temp;
    head = mylist;
    prep1 = head -> next;
    p1 = prep1 -> next;
    //prep1和p1是否需要手動後移
    bool flag;

    while(p1 != NULL)
    {   
        flag = true;
        temp = p1; 
        //由於是單向鏈表,所以只能從頭部開始檢索
        for(prep2 = head, p2 = prep2 -> next; p2 != p1; prep2 = prep2 -> next, p2 = p2 -> next)
        {   
            //發現第一個較大值
            if(p2 -> val > p1 -> val) 
            {   
                p1 = p1 -> next;
                prep1 -> next = p1; 
                prep2 -> next = temp;
                temp -> next = p2; 
                flag = false;
                break;
            }   
        }   
        //手動後移prep1和p1
        if(flag)
        {   
            prep1 = prep1 -> next;
            p1 = p1 -> next;
        }   
    }   
}
//=============插入排序====================

2、冒泡排序:
//=冒泡排序========
void bubbleSort(list mylist)
{
if((mylist -> next == NULL) || (mylist -> next -> next == NULL))
{
return;
}

node *head, * pre, * cur, *next, * end, * temp;
head = mylist;
end = NULL;
//從鏈表頭開始將較大值往後沉
while(head -> next != end)
{
    for(pre = head, cur = pre -> next, next = cur -> next; next != end; pre = pre -> next, cur = cur -> next, next = next -> next)
    {
        //相鄰的節點比較
        if(cur -> val > next -> val)
        {
            cur -> next = next -> next;
            pre -> next = next;
            next -> next = cur;
            temp = next;
            next = cur;
            cur = temp;
        }
    }
    end = cur;
}

}
//=冒泡排序========

3.簡單選擇排序:
//=簡單選擇排序====
void selectSort(list mylist)
{
if((mylist -> next == NULL) || (mylist -> next -> next == NULL))
{
return;
}

node * head, * prep1, * p1, * prep2, * p2, * premin, * min, * temp;
head = mylist;
for(prep1 = head, p1 = prep1 -> next; p1 -> next != NULL; prep1 = prep1 -> next, p1 = prep1 -> next)
{
    //保存最小節點
    premin = prep1;
    min = p1;
    for(prep2 = p1, p2 = prep2 -> next; p2 != NULL; prep2 = prep2 -> next, p2 = prep2 -> next)
    {
        if(min -> val > p2 -> val)
        {
            premin = prep2;
            min = p2;
        }
    }

    if(p1 != min)
    {
        //一定要注意這個情況
        if(p1 -> next == min)
        {
            temp = min -> next;
            prep1 -> next = min;
            min -> next = p1;
            p1 -> next = temp;
        }else{
            temp = min -> next;
            prep1 -> next = min;
            min -> next = p1 -> next;
            premin -> next = p1;
            p1 -> next = temp;
        }
    }
}

}
//=簡單選擇排序====
一、交換數據的單鏈表排序:
交換數據的排序方式就特別簡單了,因爲不用考慮前驅和後繼,只需要標記待交換的兩個節點即可。因此在這裏就直接介紹一下快速排序。

快速排序:

//=============快速排序====================

//交換節點
void swap(node * a, node * b)
{
    int temp = a -> val;
    a -> val = b -> val;
    b -> val = temp;
}

//求中間點
node * partion(node * start, node * end)
{
    if(start == end || start -> next == end)
    {   
        return start;
    }   
    //取第一個元素作爲基準元素
    node * p = start, * q = start, * refer = start;
    //從start開始向後進行一次遍歷(因爲是單鏈表,無法按從左右向中間遍歷的方法)
    while(q != end)
    {   
        if(q -> val < refer -> val) 
        {   
            p =  p -> next;
            swap(p, q); 
        }   
        q = q -> next;
    }   
    swap(p, refer);
    return p;
}
//遞歸
void quick_sort(node * start, node * end)
{
    if(start == end || start -> next == end)
    {   
        return;
    }   
    node * mid = partion(start, end);
    quick_sort(start, mid);
    quick_sort(mid -> next, end);
}

void quickSort(list mylist)
{
    if((mylist -> next == NULL) || (mylist -> next -> next == NULL))
    {
        return;
    }
    node * start = mylist -> next;
    node * end = NULL;
    quick_sort(start, end);
}

---------------------

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章