1. 程式人生 > >帶頭節點連結串列之插入排序(C語言版)

帶頭節點連結串列之插入排序(C語言版)

主要是對插入排序進行復習,先寫一個數組的插入排序。

#include <stdio.h>

void traverse(int *arr, int len);
void insert_sort(int *arr, int len);

int main() {

    int arr[5] = {3, 2, 5, 2, 1};

    printf("排序前陣列元素:");
    traverse(arr, 5);

    insert_sort(arr, 5);
    printf("排序後陣列元素:");
    traverse(arr, 5);

    return
0; } void insert_sort(int *arr, int len) { int i; int j; for(i = 1; i < len; i++) { int get = arr[i]; j = i - 1; while(j >= 0 && arr[j] >= get) { arr[j+1] = arr[j]; --j; } arr[j+1] = get; } } void traverse(int
*arr, int len) { int i; for(i = 0; i < len; i++) { printf("%d ", arr[i]); } printf("\n"); }

上面陣列的插入排序答題思路如下:
假定第一個為有序元素,其餘的為亂序元素。外層迴圈遍歷亂序元素,內層迴圈從有序元素的最後一個(i-1)向前遍歷,若找到有序元素中的某個元素小於插入的元素get,則停止迴圈。此時的j為待插入元素的前面元素下標,然後arr[j+1] = get,即把元素插入成功。

對於單鏈表進行插入排序,我們不能使其向前遍歷,因為連結串列是單向的,所以得采取其他方式。

思路如下:
1. 首先建立一個帶頭結點連結串列
這裡寫圖片描述
2. 接下來將連結串列拆為兩個部分
這裡寫圖片描述
3. 建立幾個輔助指標(暫且不討論其作用)
這裡寫圖片描述
4. 分析插入規則
這裡寫圖片描述
5. 分析插入細節
這裡寫圖片描述
這裡寫圖片描述

具體實現程式碼:

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

typedef struct Node
{
    int data;
    struct Node *pNext;
}NODE, *PNODE;

PNODE create_list(void);//建立連結串列
void traverse_list(PNODE pHead);//遍歷連結串列
bool is_empty(PNODE pHead);//判斷連結串列是否為空
int length_list(PNODE);//返回連結串列的元素個數
/*
//單鏈表插入排序演算法
*/
PNODE insert_sort_list(PNODE pHead);

int main() {
    PNODE pHead = NULL;

    pHead = create_list();
    printf("排序前元素:");
    traverse_list(pHead);

    pHead = insert_sort_list(pHead);
    printf("排序後元素:");
    traverse_list(pHead);

    return 0;
}

PNODE insert_sort_list(PNODE pHead) {
    PNODE first; //指向無序元素的第一個元素
    PNODE t; //儲存無序元素的第一個元素,將其插入到有序元素中
    PNODE p; //輔助指標
    PNODE q; //輔助指標
    PNODE head;//指向有序元素的第一個個元素

    /*
        將連結串列拆為有序元素組成的連結串列和無序元素組成的連結串列
    */
    head= pHead->pNext;
    first = head->pNext;  
    head->pNext = NULL; 

    //遍歷無序元素連結串列
    while (first != NULL) {  
        for (t = first, q = head; ((q != NULL) && (q->data < t->data)); p = q, q = q->pNext);//找無序元素中第一個元素插入的位置

        first = first->pNext; //向後移動

        if (q == head)//是要將插入的元素插入到頭結點指向的位置,也就是最小的元素
        {  
            pHead->pNext = t; 
            t->pNext = head;
            head = pHead->pNext;//此處很重要,head只有一個作用就是要指向有序元素的第一個元素位置
        }  
        else  
        {  //插入的值是在有序元素第一個元素的後面
            p->pNext = t;//p儲存插入元素的前一個元素的位置 
            t->pNext = q;//q儲存插入元素的後一個元素的位置
        }   
    }  
    return pHead;  //最後返回頭指標即可,排序完成
}

int length_list(PNODE pHead) {
    int cnt = 0;
    PNODE p = pHead->pNext;
    while(NULL != p) {
        cnt++;
        p = p->pNext;
    }

    return cnt;
}

void traverse_list(PNODE pHead) {
    PNODE p = pHead->pNext;

    while(NULL != p) {
        printf("%d ", p->data);
        p = p->pNext;
    }
    printf("\n");
    return;
}

PNODE create_list(void) {
    int i;
    int n;
    int val;
    //建立連結串列是什麼意思? --> 建立頭結點,若使用者輸入;連結串列個數,則應該加到頭結點後面

    PNODE pHead = (PNODE)malloc(sizeof(NODE));//頭結點是不能直接進行操作的
    PNODE pTail = pHead;

    pTail->data = 0;
    pTail->pNext = NULL;

    printf("請輸入您需要生成的結點個數:");
    scanf("%d", &n);

    for(i = 0; i < n; i++) {
        printf("請輸入第%d個結點的值:", i+1);
        scanf("%d", &val);

        PNODE pNew = (PNODE)malloc(sizeof(NODE));
        pNew->data = val;
        pNew->pNext = NULL;
        pTail->pNext = pNew;
        pTail = pNew;
    }

    return pHead;
}

截圖一份:
這裡寫圖片描述