插入排序的實現與優化並和選擇排序進行性能比較


插入排序
第一種:交換法
| 8 | 6 | 3 | 2 | 10 | 9 | 11 | 4 | 5 |
第一個元素就不需要考慮了,直接看第二個元素6,因為6<8,所以6與8交換位置得到:
| 6 | 8 | 3 | 2 | 10 | 9 | 11 | 4 | 5 |
在考慮第三個元素3,因為3<8,交換3和8,再比較3和6因為3<6,交換3和6得到:
| 3 | 6 | 8 | 2 | 10 | 9 | 11 | 4 | 5 |
后面以此類推
第二種:復制法:
|51|6|85|6|8|5|4|
| | 6|
將6復制一份,然后比較6之前的元素51
因為6<51,不適合放到當前位置,所以將51向后移動 ,考慮6是不是應該放到前一個位置
|51|51|85|6|8|5|4|
|6 |
因為現在6已經是第0個位置了,所以就放到這個位置。。。。以此類推
和上一個博客一樣,將之前的選擇排序寫到一個 .h 文件中來測試:
測試代碼:

 1 #ifndef INC_04_INSERTION_SORT_SORTTESTHELPER_H
 2 #define INC_04_INSERTION_SORT_SORTTESTHELPER_H
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <string>
 6 #include <ctime>
 7 #include <cassert>
 8 using namespace std;
 9 namespace SortTestHelper {
10     // 生成有n個元素的隨機數組,每個元素的隨機范圍為[rangeL, rangeR]
11         int *generateRandomArray(int n, int range_l, int range_r) {
12         int *arr = new int[n];
13         srand(time(NULL));
14         for (int i = 0; i < n; i++)
15             arr[i] = rand() % (range_r - range_l + 1) + range_l;
16         return arr;
17     }
18     // 拷貝整型數組a中的所有元素到一個新的數組, 並返回新的數組
19     int *copyIntArray(int a[], int n){
20         int *arr = new int[n];
21         copy(a, a+n, arr);
22         return arr;
23     }
24     // 打印arr數組的所有內容
25     template<typename T>
26     void printArray(T arr[], int n) {
27         for (int i = 0; i < n; i++)
28             cout << arr[i] << " ";
29             cout << endl;
30         return;
31     }
32     // 判斷arr數組是否有序
33     template<typename T>
34     bool isSorted(T arr[], int n) {
35 
36         for (int i = 0; i < n - 1; i++)
37             if (arr[i] > arr[i + 1])
38                 return false;
39         return true;
40     }
41     // 測試sort排序算法排序arr數組所得到結果的正確性和算法運行時間
42     template<typename T>
43     void testSort(const string &sortName, void (*sort)(T[], int), T arr[], int n) {
44         clock_t startTime = clock();
45         sort(arr, n);
46         clock_t endTime = clock();
47         cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s"<<endl;
48         assert(isSorted(arr, n));
49         return;
50     }
51 };
52 
53 #endif

選擇排序代碼:

 1 #ifndef INC_04_INSERTION_SORT_SELECTIONSORT_H
 2 #define INC_04_INSERTION_SORT_SELECTIONSORT_H
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 template<typename T>
 7 void selectionSort(T arr[], int n){
 8     for(int i = 0 ; i < n ; i ++){
 9         int minIndex = i;
10         for( int j = i + 1 ; j < n ; j ++ )
11             if( arr[j] < arr[minIndex] )
12                 minIndex = j;
13         swap( arr[i] , arr[minIndex] );
14     }
15 }
16 #endif 
 
        

插入函數(主函數)代碼

#include <iostream>
#include <algorithm>
#include "SortTestHelper.h"
#include "SelectionSort.h"
using namespace std;

//一,沒有優化的插入排序(交換法) 
/*
template<typename T>
void insertionSort(T arr[], int n){
//插入排序第一個元素不用考慮 
    for( int i = 1 ; i < n ; i ++ ) {
        // 尋找元素arr[i]合適的插入位置
        // 寫法一: 
//        for( int j = i ; j > 0 ; j-- )
//            if( arr[j] < arr[j-1] )
//                swap( arr[j] , arr[j-1] );
//            else
//           break;
        // 寫法二 : 
          for( int j = i ; j > 0 && arr[j] < arr[j-1] ; j -- )
                 swap( arr[j] , arr[j-1] );
    }
    return;
}
*/
//二,優化后的插入排序 (復制法)
//51,6,85,6,8,5,4
//   6
//將6復制一份,然后比較6之前的元素51
//因為6<51,不適合放到當前位置,所以將51向后移動 ,考慮6是不是應該放到前一個位置 
//51,51,85,6,8,5,4
//6
//因為現在6已經是第0個位置了,所以就放到這個位置。。。。以此類推 
        //寫法三 : 
 
template<typename T>
void insertionSort(T arr[], int n){
   for( int i = 1 ; i < n ; i ++ ) {
        // 尋找元素arr[i]合適的插入位置
        T e = arr[i];
        int j;//保存元素e應該插入的位置 
        for( j = i ; j > 0 && arr[j-1] > e ; j -- ){
            arr[j] = arr[j-1];
        }
    arr[j] = e;
    }
}
// 比較SelectionSort和InsertionSort兩種排序算法的性能效率
// 此時, 插入排序比選擇排序性能略低
int main() {
    int n = 20000;
    cout<<"Test for random array, size = "<<n<<", random range [0, "<<n<<"]"<<endl;
    int *arr1 = SortTestHelper::generateRandomArray(n,0,3);
    int *arr2 = SortTestHelper::copyIntArray(arr1, n);
    SortTestHelper::testSort("Insertion Sort", insertionSort,arr1,n);
    SortTestHelper::testSort("Selection Sort", selectionSort,arr2,n);
    delete[] arr1;
    delete[] arr2;
    cout<<endl;
    return 0;
}

進行測試:
1.首先看一下沒有進行優化的[寫法一:]插入排序和選擇排序性能比較:

 

2.然后是沒有進行優化的[寫法二:]插入排序和選擇排序性能比較:

 

可見雖然性能都差不多,但是寫法二明顯比寫法一的代碼更漂亮
結論:在隨機的,無序的情況下,即是插入排序沒有優化但是它的性能依然比選擇排序好
3.優化后的插入排序與選擇排序比較:

 

可見此時插入排序的性能遠遠大於選擇排序

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM