本書的作者是錯誤的,似乎他是一個軟弱的程序員。:)
,首先它是一個壞主意,使用類型int
作爲數組的大小。他應該使用類型size_t
或至少在頭<stddef.h>
限定,因爲陣列的大小的值可以是大於值類型int
可容納類型ptrdiff_t
。
考慮到,所有的C標準功能(如例如字符串函數),該處理陣列的尺寸限定出相應的參數爲具有類型size_t
帳戶。
下面是標準功能bsearch
的聲明。
void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
的兩個參數,nmemb
和size
,具有類型size_t
。
問題不在於用作數組大小類型的signed或unsigned int類型。問題是算法如何實現。
例如,他可以實現的算法,因爲它是在示範程序中顯示下列方式
#include <stdio.h>
size_t binary_search(const int a[], int x, size_t n)
{
size_t low = 0, high = n;
while (low < high)
{
size_t middle = low + (high - low)/2;
if (a[middle] < x)
{
low = middle + 1;
}
else if (x < a[middle])
{
high = middle;
}
else
{
return middle;
}
}
return n;
}
int main(void)
{
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
size_t N = sizeof(a)/sizeof(*a);
for (int i = -1; i <= a[N - 1] + 1; i++)
{
printf("x = %d: %zu\n", i, binary_search(a, i, N));
}
return 0;
}
程序輸出是
x = -1: 10
x = 0: 0
x = 1: 1
x = 2: 2
x = 3: 3
x = 4: 4
x = 5: 5
x = 6: 6
x = 7: 7
x = 8: 8
x = 9: 9
x = 10: 10
正如你看到的,如果一個值未找到數組然後函數返回等於數組大小的索引。
通常返回目標元素的索引的二進制搜索算法被定義爲下限算法。
下面是一個二分法搜索算法的實現示例,該算法返回目標元素存在或可能插入的較低位置。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
size_t binary_search(const int a[], int x, size_t n)
{
size_t low = 0, high = n;
while (low < high)
{
size_t middle = low + (high - low)/2;
if (a[middle] < x)
{
low = middle + 1;
}
else
{
high = middle;
}
}
return high;
}
int main(void)
{
const size_t N = 10;
int a[N];
srand((unsigned int)time(NULL));
for (size_t i = 0; i < N; i++)
{
int value = rand() % (int)N;
size_t n = binary_search(a, value, i);
if (n != i)
{
memmove(a + n + 1, a + n, (i - n) * sizeof(int));
}
a[n] = value;
for (size_t j = 0; j < i + 1; j++)
{
printf("%d ", a[j]);
}
putchar('\n');
}
return 0;
}
程序輸出可能看起來像
8
1 8
1 5 8
0 1 5 8
0 1 5 5 8
0 0 1 5 5 8
0 0 1 2 5 5 8
0 0 1 2 2 5 5 8
0 0 1 2 2 5 5 8 9
0 0 1 2 2 5 5 5 8 9
正如你看到既未簽署int
類型是在算法的實現中使用。
至於對方回答這個樣子
for (unsigned i = START_VAL; i >= 0; i--) {...} //WRONG
然後再它只是寫不正確的循環。相反,在這種情況下,for
循環的存在,應使用do-while
循環,例如
unsigned i = START_VAL;
do
{
// ...
} while (i-- != 0);
*「如果我** **被宣佈無符號練習2.10代碼是行不通的。」 * - 什麼**我**? – StoryTeller
回答你最後一個問題:'for(unsigned i = 0; i = 0; --i)'(體面的編譯器可能會給你一個警告)。 –
Abstraction
這行'mid =(low + high)/ 2;'有溢出錯誤。這與[Java庫中的這個錯誤]是一樣的(https://research.googleblog.com/2006/06/extra-extra-read-all-about-it-nearly.html) – JeremyP