直接插入法排序,vector陣列實現(有關vector陣列越界問題處理)
阿新 • • 發佈:2021-04-02
直接插入法排序,vector陣列實現(以及"vector subscript out of range"越界問題處理)
直接插入法基本原理
在從小到大的排序過程中,設定一個哨兵位,如果a[ i ] > a[ i - 1 ](i 從 1 開始計數)則由哨兵位儲存a[ i ]的value,此時哨兵大於a[ i - 1 ],從a[ i - 1 ]開始向前依次取a中各個元素與哨兵位比較大小,小於哨兵位的value值,則將其位置向後挪動一位,a[ i ]的值被替換為a[ i - 1]的值,以此類推…直到哨兵位不大於某個第 j 個元素時,因為此時原 j + 1的位置的值已經賦給了 j + 2位置,所以將哨兵位的value值賦值給 j + 1的位置即可
程式碼段
/*直接插入排序,從左到右自小而大排序,
1) 設定哨兵,A[0]~A[n-1]存放原始資料
2) A[0]~A[L-1]有序,如果A[L]<A[L-1],哨兵儲存A[L]的值
3) 從A[L-1]到A[0]依次與哨兵作比較,大於哨兵的往後移動
4) 用哨兵對移動之後空出來的位置進行賦值(也就是原A[L]的值)
5) 完成排序
輸入樣例:38 45 26 15 77 99 6 9 78 12
輸出樣例:6 9 12 15 26 38 45 77 78 99*/
#include<bits\stdc++.h>
using namespace std;
void InsertSort(vector<int> data)//直接插入排序函式
{
int shaobing; //哨兵位
int j = 0;
for (int i = 1; i < data.size(); i++)
{//i 從 1 開始計數
shaobing = 0;//每次迴圈哨兵位清零
if (data[i] < data[i - 1])
{
shaobing = data[i];
j = i - 1;
if (j >= 0 && j < data.size())
{
for (j; j >= 0 && j < data.size(); j--)//防止陣列越界
{
if(shaobing < data[j])
{
data[j + 1] = data[j];
}
else
{
break;
}
}
/*
之前寫的是:
for(j; shaobing < data[j] && j >= 0 && j < data.size();j--)
{
data[j+1] = data[j];
}
//後面都一樣
但是在執行過程中報錯“vector subscript out of range”,造成除錯中斷
然後進行單步除錯,開啟 Watch監視器
同時去看 i、j 、data[i] 、data[j] 、data[0]到data[9](因為自己設定的測試
樣例是十位數字)
在單步除錯的過程中,發現問題出在,j--的操作執行過後,j可能出現的最小值應該
為-1,我們原本的願望是j出現-1之後,代表哨兵位已經小於第一位陣列元素,並且
已經將原第一位元素的值賦給第二位的位置了,此時應該跳出迴圈,並在跳出去以後
將哨兵的值賦給第一位元素,即賦值給a[j + 1];
但是在我們希望利用j小於零的條件跳出迴圈的時候,迴圈中的判斷部分還有一句同
時執行的“shaobing < data[j]”語句,即判斷是否要發生向後賦值的語句,也會進
行判斷,則在j=-1的情況下發生陣列越界,造成中斷,報錯為"vector subscript
out of range"
處理辦法:將“shaobing < data[j]”語句拿下來在迴圈體中以if else語句配合
break跳出命令的格式實現其原功能。這樣在迴圈判斷過程中就不再會出現越界的情
況
*/
if ((j+1) >= 0 && (j+1) < data.size())
{
data[j + 1] = shaobing;
}
}
}
}
for (int i = 0; i < data.size(); i++)
{
cout << data[i] << ' ';
}
}
int main()
{
vector <int> data;
int data_in;
while (1)
{
cin >> data_in;
data.push_back(data_in);//依次輸入
if (cin.get() == '\n') //帶走回車
{
break;
}
}
//驗證輸入的正確性
/*for (int i = 0; i < data.size(); i++)
{
cout << data[i]<<' ';
}*/
InsertSort(data);
}