我正在一個陣列中進行二進制搜索,尋找陣列中的一個特定值。當我第一次寫代碼時,我的用于對陣列進行升序排序的for回圈總是在中間添加一個0,這樣我就無法搜索陣列的最后一個元素,因為中間部分現在被替換成了0,我不知道為什么,然后我以完全相同的方式重寫了程式,突然就成功了。
我注意到在新重寫的程式中,當我寫一個用于遍歷陣列并在陣列排序的回圈之前列印出其內容的回圈時,它又在中間添加了一個 0,如果我洗掉這個回圈,則一切正常。我不明白這是為什么,誰能給我解釋一下嗎?
#include <iostream>
使用 命名空間 std.com.cn>。
int main()
{
int Arr[] = {1,1, 2,2, 3,-3, 4,4,5,-5。 6,6,7,-7};
int Temp, Size, Low = 0, High, Mid, Key, Found = 0;
Size = (sizeof(Arr) / sizeof(Arr[0]) 。)
High = Size - 1。
cout<<"輸入你想測驗的鍵的值。
"。
cin>>鍵。
/*
for (int i = 0; i < Size; i ) //如果我不注釋這個回圈,0將被添加到
{ //陣列的中間,我不知道為什么
cout<<Arr[i]<<" "。
*/
for (int Rep = 1; Rep <= Size-1; Rep )
{
for (int i = 0, Temp = 0; i < Size; i )
{
if (Arr[i] > Arr[i 1] )
{
Temp = Arr[i];
Arr[i] = Arr[i 1]。
Arr[i 1] = Temp。
}
}
}
for (int i = 0; i < Size; i )
{
cout<<Arr[i]<<" "/span>。
}
for (int i = 0; i < Size; i )
{
Mid = (Low High)/2;
if (Arr[Mid] == Key)
{
Found = 1;
break;
}
else if (Arr[mid] < Key)
{
Low = Mid 1;
}
else if (Arr[Mid] > Key)
{
High = Mid-1。
}
}
if (Found)
{
cout<<"
給定的鍵值"<<Key<<" 被發現。"。
}
else; }
{
cout<<"
給定的鍵值"<<Key<<" 沒有找到。"。
}
return 0;
}
uj5u.com熱心網友回復:
這個for loop
for (int i = 0, Temp = 0; i< Size; i )
{
if (Arr[i] > Arr[i 1] )
{
Temp = Arr[i];
Arr[i] = Arr[i 1]。
Arr[i 1] = Temp。
}
引起了未定義的行為,因為在這個if陳述句中,當i等于Size - 1時,有一個試圖在陣列之外解除對記憶體的參考
if (Arr[i] > Arr[i 1] )
{
Temp = Arr[i];
Arr[i] = Arr[i 1]。
Arr[i 1] = Temp。
}
在運算式Arr[i 1]中。
你可以用以下方式重寫這個回圈
for (int i = 1; i < Size; i )
{
if (Arr[i] < Arr[i-1] )
{
int Temp = Arr[i];
Arr[i] = Arr[i-11] 。
Arr[i-1] = Temp。
}
在這個回圈中也會出現同樣的問題
for (int i = 0; i < Size; i )
{
Mid = (Low High)/2;
if (Arr[Mid] == Key)
{
Found = 1;
break;
}
else if (Arr[mid] < Key)
{
Low = Mid 1;
}
else if (Arr[Mid] > Key)
{
High = Mid-1。
}
}
因為回圈迭代的數量可能大于二進制搜索方法的要求。結果又是Mid可以有一個無效的值作為陣列中的索引。
uj5u.com熱心網友回復:
不要寫使用命名空間std;/code>。
但是,你可以在CPP檔案(不是H檔案)或在一個函式里面把個別的使用std::string;等(見SF.7。)
你實際上不需要 學習存在 在C 中,有直接的方法來獲得這個大小,但是你不需要,因為下一點。
注意,按照慣例(即標準庫中的所有內容, 在現實生活中,你將呼叫 一個完全通用的演算法將更加謹慎,只在迭代器上使用通用的操作,所以它將適用于任何東西而不僅僅是原始陣列。 但它開始以標準庫的方式做事,并遵循共同的慣例。
你很少需要在其他代碼中單獨獲得一個原始陣列的大小。 正如我所展示的,你通常使用int Temp, Size, Low = 0, High, Mid, Key, Found = 0;/code>
在變數準備好被初始化之前,不要宣告這些變數。
不要在一條陳述句中把多個變數的宣告混在一起。
Temp(見下文),而Found應該是bool。
Temp = Arr[i];
Arr[i] = Arr[i 1] 。
Arr[i 1] = Temp。
std::swap。 一般來說,通過閱讀<algorithms>來熟悉可用的東西。Size = (sizeof(Arr) / sizeof(Arr[0]));
不要這樣做!
這是一個很脆弱的C語言習慣,因為很容易不小心使用一個衰減為指標的值,而不是獲得陣列的大小。 在C 中,有直接的方法來獲得這個大小,但是你不需要,因為下一點。
不要使用下標,而要使用iterators。
你可以對原始陣列使用非成員函式begin和end。
using std::begin。
using std::end;
auto low= begin(Arr)。
auto high= end(Arr)。
end是超過結尾的一個,而不是指向最后的元素。sort來對陣列進行排序,然后呼叫upper_bound或lower_bound來進行二進制搜索。 但是你正在學習這個演算法是如何作業的,所以你要從頭開始自己實作它。 然而,你可以將你的結果與庫函式進行比較,以測驗結果!while(low < high){
const auto dist = high-low;
const auto mid = low (dist/2)。
if (*mid == target) return mid;
if (*mid < target) high=mid-1;
else low=mid 1;
}
關于陣列大小的postscript。
begin和end作為迭代器,而不關心相應的索引值。 甚至不是所有種類的集合都有這樣的索引!
當使用模板傳遞整個陣列時,它可以自然而然地被拾起。 例如,
template <typename T,size_t N>
void do_something (T (&arr) [N]) {
在這個函式中,N將有陣列大小。
雖然有標準的函式來獲取大小。 最直接的,也是針對原始陣列的,是extent_v,所以你可以寫:
size_t Size = std::extent_v<typeof(Arr)>;
這是很尷尬的,因為你有一個變數名(Arr)而不是一個型別名。 但是不要害怕,有一個更通用的函式,即非成員的size,它適用于任何東西,包括陣列:
size_t Size = std::size(Arr)。
這樣做是可以的,因為你知道Arr實際上是一個原始陣列。 但這并不是真正的正統,你應該把代碼寫得一般化和通用化,即使你不寫模板,也會大大有助于維護。 在編輯程式以進行改進和修復時,改變某物的型別是一件很常見的事情,而當這一做法 "僅僅是有效的",并且不需要進行其他的改變來匹配時,那就太好了!
"std two-step"的習慣用法
。using std::size。
size_t Size = std::size(Arr)。
C 20的更新
但是需要 "std兩步法 "的問題現在已經納入了標準庫,所以在較新的編譯器上,你可以改用:size_t Size = std::ranges::size(Arr)。
而且它總是有效的,對于原始陣列、std中定義的集合,以及其他集合類也是如此。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/310848.html
標籤:
上一篇:如何使排序功能更簡單(或更短)?
