C++ 插入排序演算法的實現與改進(含筆試面試題)
阿新 • • 發佈:2019-02-05
插入排序是一種最簡單直觀的排序演算法,它的工作原理是通過構建有序序列,對於未排序資料,在已排序序列中從後向前掃描,找到相應位置並插入。
簡單小tips:假設一個數列:1、2、5、3。插入排序的思想就是從1開始每次向前遍歷:
2比1大,為有序
5比2大,5比1大,為有序
3比5小,無序,交換,交換之後3與2比,3與1比有序
結果為 :1、2、3、5
演算法步驟:
1)將第一待排序序列第一個元素看做一個有序序列,把第二個元素到最後一個元素當成是未排序序列。
2)從頭到尾依次掃描未排序序列,將掃描到的每個元素插入有序序列的適當位置。(如果待插入的元素與有序序列中的某個元素相等,則將待插入元素插入到相等元素的後面。)
實現程式碼:過載插入排序的函式,一次的改進:二分法查詢插入位置
/*************************************************************************** * @file main.cpp * @author MISAYAONE * @date 24 March 2017 * @remark 24 March 2017 * @theme Insertion Sort ***************************************************************************/ #include <iostream> #include <vector> using namespace std; //傳入一對迭代器,標準的插入排序 void Insertion_sort(vector<int>::iterator begin,vector<int>::iterator end) { for (auto p1 = begin; p1 != end; ++p1) { auto p2 = p1; while ((p2 != begin) && *(p2-1)>*p2) { int temp = *(p2); *p2 = *(p2-1); *(p2-1) = temp; --p2; } } } //對函式進行過載,傳入指向陣列的指標和陣列大小,同時進行第一次改進(也稱二分插入排序) void Insertion_sort(int a[],size_t size) { for (size_t i = 1; i != size; ++i) { int low = 0;//排好元素的下界 int high = i;//排好元素的上界 if (a[i-1] > a[i])//判斷元素是否需要排序,滿足條件則需要排序 { int temp = a[i];//待排元素 a[i] = a[i-1];//直接先將排好元素中的最後一個元素後移一位 //while迴圈使用二分法找到插入位置 while (low <= high) { int mid = (low+high)/2; if (temp < a[mid])//待排元素之前的序列肯定是有序的,找到其中位數比較大小 { high = mid-1; } else low = mid+1; } size_t j=i-1; for(j;j>=high+1;j--)//移動元素 a[j+1]=a[j]; a[j+1] = temp; } } } int main(int argc, char **argv) { int a[10] = {2,5,6,3,1,4,8,7,9,0}; vector<int> vec(a,a+10); Insertion_sort(vec.begin(),vec.end()); for (size_t i = 0; i < vec.size(); ++i) { cout<<vec[i]<<" "; } Insertion_sort(a,10); cout<<endl; for (size_t i = 0; i < 10; ++i) { cout<<a[i]<<" "; } cin.get(); return 0; }
複雜度分析:
最優時間複雜度:當輸入陣列就是排好序的時候,複雜度為O(n),而快速排序在這種情況下會產生O(n^2)的複雜度。
最差時間複雜度:當輸入陣列為倒序時,複雜度為O(n^2)
插入排序比較適合用於“少量元素的陣列”
插入排序的複雜度和逆序對的個數一樣,當陣列倒序時,逆序對的個數為n(n-1)/2,因此插入排序複雜度為O(n^2)。
特點分析:穩定演算法(stable)、in
place演算法
例題1:請寫出連結串列的插入排序程式:
template<typename T> struct list_node { struct list_node<T> *next; T value; }; template<typename T> struct _list { struct list_node<T> *head; int size; }; template<typename T> void SortLink(struct _list<T> * link) { struct list_node<T> *pHead,*pRear,*p,*tp; if (!link) return; for (pHead=link->head,pRear=0;pHead;pHead=pHead->next) { for (tp=pHead,p=pHead->next;p;tp=p,p=p->next) if (pHead->value>=p->value) tp->next=p->next,p->next=pHead,pHead=p,p=tp; if (!pRear) link->head=pHead; else pRear->next=pHead; pRear=pHead; } }