久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3656|回復: 0
打印 上一主題 下一主題
收起左側

C語言排序算法詳解

[復制鏈接]
跳轉到指定樓層
樓主
ID:399983 發表于 2018-10-11 14:57 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式

對排序做了一些詳細的介紹,需要的可以看看。

簡介
其中排序算法總結如下:
1.交換排序
  交換排序的基本思想都為通過比較兩個數的大小,當滿足某些條件時對它進行交換從而達到排序的目的。
1.1冒泡排序
基本思想:比較相鄰的兩個數,如果前者比后者大,則進行交換。每一輪排序結束,選出一個未排序中最大的數放到數組后面。
代碼:
#include<stdio.h>
//冒泡排序算法
void bubbleSort(int *arr, int n) {
    for (int i = 0; i<n - 1; i++)
        for (int j = 0; j < n - i - 1; j++)
        {
            //如果前面的數比后面大,進行交換
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp;
            }
        }
}
int main() {
    int arr[] = { 10,6,5,2,3,8,7,4,9,1 };
    int n = sizeof(arr) / sizeof(int);
    bubbleSort(arr, n);
    printf("排序后的數組為:\n");
    for (int j = 0; j<n; j++)
        printf("%d ", arr[j]);
    printf("\n");
return 0;

分析:
  最差時間復雜度為O(n^2),平均時間復雜度為O(n^2)。穩定性:穩定。輔助空間O(1)。
升級版冒泡排序法:通過從低到高選出最大的數放到后面,再從高到低選出最小的數放到前面,如此反復,直到左邊界和右邊界重合。當數組中有已排序好的數時,這種排序比傳統冒泡排序性能稍好。
代碼:
#include<stdio.h>
//升級版冒泡排序算法
void bubbleSort_1(int *arr, int n) {
    //設置數組左右邊界
    int left = 0, right = n - 1;
    //當左右邊界未重合時,進行排序
    while (left<right) {
        //從左到右遍歷選出最大的數放到數組右邊
        for (int i =left; i < right; i++)
        {
            if (arr[ i] > arr[i + 1])
            {
                int temp = arr[ i]; arr[ i] = arr[i + 1]; arr[i + 1] = temp;
            }
        }
        right--;
        //從右到左遍歷選出最小的數放到數組左邊
        for (int j = right;j> left; j--)
        {
            if (arr[j + 1] < arr[j])
            {
                int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp;
            }
        }
        left++;
    }
}
int main() {
    int arr[] = { 10,6,5,2,3,8,7,4,9,1 };
    int n = sizeof(arr) / sizeof(int);
    bubbleSort_1(arr, n);
    printf("排序后的數組為:\n");
    for (int j = 0; j<n; j++)
        printf("%d ", arr[j]);
    printf("\n");
    return 0;
}
1.2. 快速排序
  基本思想:選取一個基準元素,通常為數組最后一個元素(或者第一個元素)。從前向后遍歷數組,當遇到小于基準元素的元素時,把它和左邊第一個大于基準元素的元素進行交換。在利用分治策略從已經分好的兩組中分別進行以上步驟,直到排序完成。下圖表示了這個過程。
代碼:
#include<stdio.h>
void swap(int *x, int *y) {
    int tmp = *x;
    *x = *y;
    *y = tmp;
}
//分治法把數組分成兩份
int patition(int *a, int left,int right) {
    int j = left;    //用來遍歷數組
    int i = j - 1;    //用來指向小于基準元素的位置
    int key = a[right];    //基準元素
    //從左到右遍歷數組,把小于等于基準元素的放到左邊,大于基準元素的放到右邊
    for (; j < right; ++j) {
        if (a[j] <= key)
            swap(&a[j], &a[++i]);
    }
    //把基準元素放到中間
    swap(&a[right], &a[++i]);
    //返回數組中間位置
    return i;
}
//快速排序
void quickSort(int *a,int left,int right) {
    if (left>=right)
        return;
    int mid = patition(a,left,right);
    quickSort(a, left, mid - 1);
    quickSort(a, mid + 1, right);
}
int main() {
    int a[] = { 10,6,5,7,12,8,1,3,11,4,2,9,16,13,15,14 };
    int n = sizeof(a) / sizeof(int);
    quickSort(a, 0,n-1);
    printf("排序好的數組為:");
    for (int l = 0; l < n; l++) {
        printf("%d ", a[l]);
    }
    printf("\n");
    return 0;
}

分析:  
  最差時間復雜度:每次選取的基準元素都為最大(或最小元素)導致每次只劃分了一個分區,需要進行n-1次劃分才能結束遞歸,故復雜度為O(n^2);最優時間復雜度:每次選取的基準元素都是中位數,每次都劃分出兩個分區,需要進行logn次遞歸,故時間復雜度為O(nlogn);平均時間復雜度:O(nlogn)。穩定性:不穩定的。輔助空間:O(nlogn)。
  當數組元素基本有序時,快速排序將沒有任何優勢,基本退化為冒泡排序,可在選取基準元素時選取中間值進行優化。

2. 插入排序
2.1 直接插入排序
基本思想:和交換排序不同的是它不用進行交換操作,而是用一個臨時變量存儲當前值。當前面的元素比后面大時,先把后面的元素存入臨時變量,前面元素的值放到后面元素位置,再到最后把其值插入到合適的數組位置。 
代碼:
#include<stdio.h>
void InsertSort(int  *a, int n) {
    int tmp = 0;
    for (int i = 1; i < n; i++) {
        int j = i - 1;
        if (a[ i] < a[j]) {
            tmp = a[ i];
            a[ i] = a[j];
            while (tmp < a[j-1]) {
                a[j] = a[j-1];
                j--;
            }
            a[j] = tmp;
        }
    }
}
int main() {
    int a[] = { 11,7,9,22,10,18,4,43,5,1,32};
    int n = sizeof(a)/sizeof(int);
    InsertSort(a, n);
    printf("排序好的數組為:");
    for (int i = 0; i < n; i++) {
        printf(" %d", a[ i]);
    }
    printf("\n");
    return 0;
}

分析:
最壞時間復雜度為數組為逆序時,為O(n^2)。最優時間復雜度為數組正序時,為O(n)。平均時間復雜度為O(n^2)。輔助空間O(1)。穩定性:穩定。
2.2 希爾(shell)排序
  基本思想為在直接插入排序的思想下設置一個最小增量dk,剛開始dk設置為n/2。進行插入排序,隨后再讓dk=dk/2,再進行插入排序,直到dk為1時完成最后一次插入排序,此時數組完成排序。
代碼:
#include<stdio.h>
//    進行插入排序
//    初始時從dk開始增長,每次比較步長為dk
void Insrtsort(int *a, int n,int dk) {
    for (int i = dk; i < n; ++i) {
        int j = i - dk;
        if (a[ i] < a[j]) {    //    比較前后數字大小
            int tmp = a[ i];        //    作為臨時存儲   
            a[ i] = a[j];
            while (a[j] > tmp) {    //    尋找tmp的插入位置
                a[j+dk] = a[j];
                j -= dk;
            }
            a[j+dk] = tmp;        //    插入tmp
        }
    }
}
void ShellSort(int *a, int n) {
    int dk = n / 2;        //    設置初始dk
    while (dk >= 1) {
        Insrtsort(a, n, dk);
        dk /= 2;
    }
}
int main() {
    int a[] = { 5,12,35,42,11,2,9,41,26,18,4 };
    int n = sizeof(a) / sizeof(int);
    ShellSort(a, n);
    printf("排序好的數組為:");
    for (int j = 0; j < n; j++) {
        printf("%d ", a [j]);
    }
    return 0;
}

分析:
  最壞時間復雜度為O(n^2);最優時間復雜度為O(n);平均時間復雜度為O(n^1.3)。輔助空間O(1)。穩定性:不穩定。希爾排序的時間復雜度與選取的增量有關,選取合適的增量可減少時間復雜度。

3. 選擇排序
3.1.直接選擇排序
基本思想:依次選出數組最小的數放到數組的前面。首先從數組的第二個元素開始往后遍歷,找出最小的數放到第一個位置。再從剩下數組中找出最小的數放到第二個位置。以此類推,直到數組有序。
代碼:
#include<stdio.h>
void SelectSort(int *a, int n) {
    for (int i = 0; i < n; i++)
    {
        int key = i;    //    臨時變量用于存放數組最小值的位置
        for (int j = i + 1; j < n; j++) {
            if (a[j] < a[key]) {   
                key = j;    //    記錄數組最小值位置
            }
        }
            if (key != i)
            {
                int tmp = a[key]; a[key] = a[ i]; a[ i] = tmp;    //    交換最小值
            }
    }
}
int main() {
    int a[] = { 12,4,15,2,6,22,8,10,1,33,45,24,7 };
    int n = sizeof(a) / sizeof(int);
    SelectSort(a, n);
    printf("排序好的數組為: ");
    for (int k = 0; k < n; k++)
        printf("%d ", a[k]);
    printf("\n");
    return 0;
}
分析:
最差、最優、平均時間復雜度都為O(n^2)。輔助空間為O(1)。穩定性:不穩定。

3.2.堆(Heap)排序
  基本思想:先把數組構造成一個大頂堆(父親節點大于其子節點),然后把堆頂(數組最大值,數組第一個元素)和數組最后一個元素交換,這樣就把最大值放到了數組最后邊。把數組長度n-1,再進行構造堆,把剩余的第二大值放到堆頂,輸出堆頂(放到剩余未排序數組最后面)。依次類推,直至數組排序完成。
  下圖為堆結構及其在數組中的表示。可以知道堆頂的元素為數組的首元素,某一個節點的左孩子節點為其在數組中的位置*2,其右孩子節點為其在數組中的位置*2+1,其父節點為其在數組中的位置/2(假設數組從1開始計數)。
下圖為怎么把一個無序的數組構造成一個大堆頂結構的數組的過程,注意其是從下到上,從右到左,從右邊第一個非葉子節點開始構建的。
代碼:
#include<stdio.h>
//  創建大堆頂,i為當節點,n為堆的大小
//    從第一個非葉子結點i從下至上,從右至左調整結構
//    從兩個兒子節點中選出較大的來與父親節點進行比較
//    如果兒子節點比父親節點大,則進行交換
void CreatHeap(int a[], int i, int  n) {
    //    注意數組是從0開始計數,所以左節點為2*i+1,右節點為2*i+2
    for (; i >= 0; --i)
    {
        int left = i * 2 + 1;    //左子樹節點
        int right = i * 2 + 2;    //右子樹節點
        int j = 0;
        //選出左右子節點中最大的
        if (right < n) {
            a[left] > a[right] ? j= left : j = right;
        }
        else
            j = left;
        //交換子節點與父節點
        if (a[j] > a[ i]) {
            int tmp = a[ i];
            a[ i] = a[j];
            a[j] = tmp;
        }
    }
}
//    進行堆排序,依次選出最大值放到最后面
void HeapSort(int a[], int n) {
    //初始化構造堆
    CreatHeap(a, n/2-1, n);
  //交換第一個元素和最后一個元素后,堆的大小減1
    for (int j = n-1; j >= 0; j--) {
        //最后一個元素和第一個元素進行交換
        int tmp = a[0];
        a[0] = a[j];
        a[j] = tmp;
        int i = j / 2 - 1;
        CreatHeap(a, i, j);
    }
}
int main() {
    int a[] = { 10,6,5,7,12,8,1,3,11,4,2,9,16,13,15,14 };
    int n = sizeof(a) / sizeof(int);
    HeapSort(a, n);
    printf("排序好的數組為:");
    for (int l = 0; l < n; l++) {
        printf("%d ", a[l]);
    }
    printf("\n");
    return 0;
}

分析:
  最差、最優‘平均時間復雜度都為O(nlogn),其中堆的每次創建重構花費O(lgn),需要創建n次。輔助空間O(1)。穩定性:不穩定。

4. 歸并排序
  基本思想:歸并算法應用到分治策略,簡單說就是把一個答問題分解成易于解決的小問題后一個個解決,最后在把小問題的一步步合并成總問題的解。這里的排序應用遞歸來把數組分解成一個個小數組,直到小數組的數位有序,在把有序的小數組兩兩合并而成有序的大數組。
  下圖為展示如何歸并的合成一個數組。


下圖展示了歸并排序過程各階段的時間花費。

代碼:
#include <stdio.h>
#include <limits.h>
// 合并兩個已排好序的數組
void Merge(int a[], int left, int mid, int right)
{
    int len = right - left + 1;        //    數組的長度
    int *temp = new int[len];       // 分配個臨時數組
    int k = 0;
    int i = left;                   // 前一數組的起始元素
    int j = mid + 1;                // 后一數組的起始元素
    while (i <= mid && j <= right)
    {
        //    選擇較小的存入臨時數組
        temp[k++] = a[ i] <= a[j] ? a[i++] : a[j++];
    }
    while (i <= mid)
    {
        temp[k++] = a[i++];
    }
    while (j <= right)
    {
        temp[k++] = a[j++];
    }
    for (int k = 0; k < len; k++)
    {
        a[left++] = temp[k];
    }
}
// 遞歸實現的歸并排序
void MergeSort(int a[], int left, int right)
{
    if (left == right)   
        return;
    int mid = (left + right) / 2;
    MergeSort(a, left, mid);
    MergeSort(a, mid + 1, right);
    Merge(a, left, mid, right);
}
int main() {
    int a[] = { 5,1,9,2,8,7,10,3,4,0,6 };
    int n = sizeof(a) / sizeof(int);
    MergeSort(a, 0, n - 1);
    printf("排序好的數組為:");
    for (int k = 0; k < n; ++k)
        printf("%d ", a[k]);
    printf("\n");
    return 0;
}

分析:
  最差、最優、平均時間復雜度都為O(nlogn),其中遞歸樹共有lgn+1層,每層需要花費O(n)。輔助空間O(n)。穩定性:穩定。


完整的Word格式文檔51黑下載地址:
排序算法.docx (447.23 KB, 下載次數: 9)


評分

參與人數 2黑幣 +60 收起 理由
YJGG + 10 贊一個!
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日批免费在线观看 | av免费网站在线观看 | 亚洲欧美精品国产一级在线 | 国产九九精品 | 欧美一页 | 午夜性视频| 亚洲一区在线播放 | 久久久久国产一区二区三区不卡 | h视频在线观看免费 | 粉嫩一区二区三区国产精品 | 91免费看片 | 午夜影院污 | 精品一区二区av | 高清黄色 | 欧美日韩中文字幕在线 | 在线观看免费av网 | 一区二区三区免费在线观看 | 中文字幕亚洲一区 | 亚洲精品456| 国产亚洲精品美女久久久久久久久久 | 看a网站| 羞羞视频网页 | 欧美区在线 | av日韩精品| 久久国 | 最新午夜综合福利视频 | 99精品一区二区三区 | 婷婷五月色综合香五月 | 成人免费淫片aa视频免费 | 人人插人人| 欧美日韩在线免费观看 | 欧美日高清 | 亚洲区视频 | 亚洲欧美激情精品一区二区 | 一区二区精品 | 蜜桃视频一区二区三区 | 天天草天天操 | 涩涩视频网 | 久久一二 | 国产精品久久久久久久久久久免费看 | a级在线免费观看 |