本文將在可視化算法一(傳送門)的基礎上實現插入排序,其實就是多添加了一個實現插入排序的函數,再將Widget裏的構造函數中的goBubble更換成goInsertion就可以了。
先介紹一下插入排序,先給倆個官方介紹的傳送門(百度百科和Wiki對插入排序的介紹)
插入排序又可分爲直接插入排序和折半插入排序,其中折半插入排序只是折半查找合適的位子。其實也可以結合撲克牌的理牌過程來理解。
直接插入排序(straight Insertion Sort)的基本操作時將一個記錄擦汗如到已經排好序的有序表中,從而得到一個新的並且記錄數增1的有序表。代碼整體很簡單,就是不斷將較前者小的數插到有序表的合理位子。代碼如下:
void Bubble::goInsertion()
{
//直接插入排序
for (int i = 1; i < length;i++) {
int j ;
if(data[i] < data[i - 1]){ //滿足
int temp = data[i];
for (j = i - 1;j>= 0&&temp < data[j];j--) {//將比它大的數字往後挪一個位子
data[j+1] = data[j];
bubbleSignal(j);
QThread::msleep(static_cast<unsigned int>(mDelay));
}
data[j + 1] = temp;
bubbleSignal(j);
QThread::msleep(static_cast<unsigned int>(mDelay));
}
}
}
運行結果,由於我用的截取gif文件的上限時間是20ms,所以在這裏設置的延時是10ms,導致有點快,還請見諒。
總結,本來還想接着實現以下折半插入算法,可是仔細想了想,折半插入是優化查找合適的位子,但數組還是得進行那麼多挪位,那不如直接邊挪位邊判斷位子合不合適呢,就沒實現了,如果讀者有意,可嘗試實現。很容易看出插入算法的時間複雜度是O(n^2),具體介紹還得看上面倆個傳送門的。
另外,我將Bubble類中rand函數修改了下,以免出現相同的數據
void Bubble::rand()
{
if(data == nullptr)
throw "數據不合理";
bool flag[length];
for(int i = 0; i < length; i++)
flag[i] = false;
for(int i = 0; i < length ; i++){
while(1){
int r = qrand()%max + 1;
if(flag[r-1] == false){
data[i] = r;
flag[r-1]= true;
break;
}
}
}
}