1. 程式人生 > >Linux c 八種排序

Linux c 八種排序

#include<stdio.h>
#include<stdlib.h>
//氣泡排序
void bubleSort(int data[], int n);
//快速排序
void quickSort(int data[], int low, int high);
int findPos(int data[], int low, int high);
//插入排序
void bInsertSort(int data[], int n);
//希爾排序
void shellSort(int data[], int n);
//選擇排序
void selectSort(int data[], int n);
//堆排序
void heapSort(int data[], int n);
void swap(int data[], int i, int j);
void heapAdjust(int data[], int i, int n);
//歸併排序
void mergeSort(int data[], int first, int last);
void merge(int data[], int low, int mid, int high);
//基數排序
void radixSort(int data[], int n);
int getNumPos(int num, int pos);

int main() {
    int data[10] = {43, 65, 4, 23, 6, 98, 2, 65, 7, 79};
    int i;
    printf("原先陣列:");
    for(i=0;i<10;i++) {
        printf("%d    ", data[i]);
    }
    printf("\n");
    /*printf("氣泡排序:");
    bubleSort(data, 10);
    for(i=0;i<10;i++) {
        printf("%d    ", data[i]);
    }
    printf("\n");
    printf("快速排序:");
    quickSort(data, 0, 9);
    for(i=0;i<10;i++) {
        printf("%d    ", data[i]);
    }
    printf("\n");
    printf("插入排序:");
    bInsertSort(data,10);
    for(i=0;i<10;i++) {
        printf("%d    ", data[i]);
    }
    printf("\n");
    printf("希爾排序:");
    shellSort(data, 10);
    for(i=0;i<10;i++) {
        printf("%d    ", data[i]);
    }
    printf("\n");
    printf("選擇排序:");
    selectSort(data, 10);
    for(i=0;i<10;i++) {
        printf("%d    ", data[i]);
    }
    printf("\n");
    int data[11] = {-1, 43, 65, 4, 23, 6, 98, 2, 65, 7, 79};
    int i;
    printf("原先陣列:");
    int data[11] = {-1, 43, 65, 4, 23, 6, 98, 2, 65, 7, 79};
    for(i=1;i<11;i++) {
        printf("%d    ", data[i]);
    }
    printf("\n");
    printf(" 堆排序:");
    heapSort(data, 10);
    for(i=1;i<11;i++) {
        printf("%d    ", data[i]);
    }
    printf("\n");
    printf("歸併排序:");
    mergeSort(data, 0, 9);
    for(i=0;i<10;i++) {
        printf("%d    ", data[i]);
    }
    printf("\n");*/
    printf("基數排序:");
    radixSort(data, 10);
    for(i=0;i<10;i++) {
        printf("%d    ", data[i]);
    }
    printf("\n");
    return 0;
}

/*--------------------氣泡排序---------------------*/
void bubleSort(int data[], int n) {
    int i,j,temp;
    //兩個for迴圈,每次取出一個元素跟陣列的其他元素比較
    //將最大的元素排到最後。
    for(j=0;j<n-1;j++) {
        //外迴圈一次,就排好一個數,並放在後面,
        //所以比較前面n-j-1個元素即可
        for(i=0;i<n-j-1;i++) {
            if(data[i]>data[i+1]) {
                temp = data[i];
                data[i] = data[i+1];
                data[i+1] = temp;
            }
        }
    }  
}

/*--------------------快速排序---------------------*/
int findPos(int data[], int low, int high) {
    //將大於t的元素趕到t的左邊,大於t的元素趕到t的右邊
    int t = data[low];
    while(low < high) {
        while(low < high && data[high] >= t) {
            high--;
        }
        data[low] = data[high];
        while(low < high && data[low] <=t) {
            low++;
        }
        data[high] = data[low];
    }
    data[low] = t;
    //返回此時t在陣列中的位置
    return low;
}
//在陣列中找一個元素,對大於該元素和小於該元素的兩個陣列進行再排序
//再對兩個陣列分為4個數組,再排序,直到最後每組只剩下一個元素為止
void quickSort(int data[], int low, int high) {
    if(low > high) {
        return;
    }
    int pos = findPos(data, low, high);
    quickSort(data, low, pos-1);
    quickSort(data, pos+1, high); 
}

/*--------------------插入排序---------------------*/
void bInsertSort(int data[], int n) {
    int low,high,mid;
    int temp,i,j;
    for(i=1;i<n;i++) {
        low = 0;
        //把data[i]元素插入到它的前面data[0-(i-1)]中
        temp =data[i];
        high = i-1;
        //該while是折半,縮小data[i]的範圍(優化手段)
        while(low <= high) {
            mid = (low+high)/2;
            if(data[mid] > temp) {
                high = mid-1;
            }
            else {
                low = mid+1;
            }
        }
        int j = i;
        //讓data與已經排序好的陣列的各個元素比較,小的放前面
        while((j > low) && data[j-1] > temp) {
            data[j] = data[j-1];
            --j;
        }
        data[low] = temp;
    }
}

/*--------------------希爾排序---------------------*/
void shellSort(int * data, int n) {
    int step,i,j,key;
    //將陣列按照step分組,不斷二分到每組只剩下一個元素
    for(step=n/2;step>0;step/=2) {
        //將每組中的元素排序,小的在前
        for(i=step;i<n;i++) {
            key = data[i];
            for(j=i-step;j>=0 && key<data[j];j-=step) {
                data[j+step] = data[j];
            }
            //和上面的for迴圈一起,將組中小的元素換到陣列的前面
            data[j+step] = key;
        }
    }
}

/*--------------------選擇排序---------------------*/
void selectSort(int data[], int n) {
    int i,j,mix,temp;
    //每次迴圈陣列,找出最小的元素,放在前面,前面的即為排序好的
    for(i=0;i<n-1;i++) {
        //假設最小元素的下標
        int mix = i;
        //將上面假設的最小元素與陣列比較,交換出最小的元素的下標
        for(j=i+1;j<n;j++) {
            if(data[j] < data[mix]) {
                mix = j;
            }
        }
        //若陣列中真的有比假設的元素還小,就交換
        if(i != mix) {
            temp = data[i];
            data[i] = data[mix];
            data[mix] = temp;
        }
    }
}

/*--------------------堆排序---------------------*/
//堆排序將陣列先組成二叉樹,預設從陣列的data[1]開始排,data[0]是
//無效資料
void heapSort(int data[], int n) {
    int i;
    //先將陣列組成一棵完全二叉樹
    //從2/n開始,就是從倒數第二排結點往前開始
    for(i=n/2;i>0;i--) {
        heapAdjust(data, i, n);
    }
    //迴圈每個結點,將大的結點交換到堆頂
    for(i=n;i>1;i--) {
        swap(data, 1, i);
        //每次交換完都要調整二叉樹,將剩下的最大的結點交換到堆頂
        heapAdjust(data, 1, i-1);
    }
}
//交換函式
void swap(int data[], int i, int j) {
    int temp;
    temp = data[i];
    data[i] = data[j];
    data[j] = temp;
}
void heapAdjust(int data[], int i, int n) {
    int j, temp;
    //假設第一個結點的元素是最大的
    temp = data[i];
    //i結點:2*i是i結點的左結點,2*i+1是i結點的右結點
    //把結點元素大的交換到前面
    for(j=2*i;j<=n;j*=2) {
        if(j < n && data[j] < data[j+1]) {
            j++;
        }
        if(temp >= data[j]) {
            break;
        }
        data[i] = data[j];
        i = j;
    }
    data[i] = temp;
}

/*--------------------歸併排序---------------------*/
void mergeSort(int data[], int first, int last) {
    int mid = 0;
    //將陣列不停的二分分組再組合,直到每組只剩一個元素
    if(first < last) {
        mid = (first+last)/2;
        mergeSort(data, first, mid);
        mergeSort(data, mid+1, last);
        merge(data, first, mid, last);
    }
    return;
}
void merge(int data[], int low, int mid, int high) {
    int i, k;
    //定義一個臨時陣列存放傳進來的無序陣列排好序之後的陣列
    int *temp = (int *)malloc((high-low+1)*sizeof(int));
    //將無序陣列分成兩個序列
    int left_low = low;
    int left_high = mid;
    int right_low = mid+1;
    int right_high = high;
    //將兩個序列比較排序,小的排前
    for(k=0;left_low<=left_high && right_low<=right_high;k++) {
        if(data[left_low]<=data[right_low]) {
            temp[k] = data[left_low++];
        }
        else{
            temp[k] = data[right_low++];
        }
    }
    //左序列如果有剩下元素未排序,加到臨時陣列的末尾
    if(left_low <= left_high) {
        for(i=left_low;i<=left_high;i++) {
            temp[k++] = data[i];
        }
    }
    //右序列如果有剩下元素未排序,加到臨時陣列的末尾
    if(right_low <= right_high) {
        for(i=right_low;i<=right_high;i++) {
            temp[k++] = data[i];
        }
    }
    //將排好序的小分組轉移到原陣列中
    for(i=0;i<high-low+1;i++) {
        data[low+i] = temp[i];
    }
    free(temp);
    return;
}
/*--------------------基數排序---------------------*/
//該函式的作用是找出num的pos位數的數字(比如:23的個位數數字是3)
int getNumPos(int num, int pos) {
    int i;
    int temp = 1;
    for(i=0;i<pos-1;i++) {
        temp *= 10;
    }
    return (num / temp) % 10;
}
void radixSort(int data[], int n) {
    int i,j,k,pos,num,index;
    //這幾句話是建立一個從0-9(行)× (n+1)(列)的網格,第一列從上往下是0-9,
    //第二列是該行包含的元素個數,預設為0個
    int *radixArrays[10];
    for(i=0;i<10;i++) {
        radixArrays[i] = (int *)malloc(sizeof(int) * (n+1));
        radixArrays[i][0] = 0;
    }
    //pos最大為31為數,計算機能承受的最大範圍了
    for(pos=1;pos<=31;pos++) {
        //該for迴圈是將陣列的元素按照位數(pos)的值放進網格內
        for(i=0;i<n;i++) {
            num = getNumPos(data[i], pos);
            index = ++radixArrays[num][0];
            radixArrays[num][index] = data[i];
        }
        //該for迴圈是將上面的for迴圈已經按照某個位數(pos)排列好的元素存入陣列
        for(i=0,j=0;i<10;i++) {
            for(k=1;k<=radixArrays[i][0];k++) {
                data[j++] = radixArrays[i][k];
            }
            //清空網格,以便給下個位數排列
            radixArrays[i][0] = 0;
        }
    }
}

 

 以上排序演算法的優劣(時間複雜度和空間複雜度對比):

這裡寫圖片描述