/* Binary search. * * Implementation history: * 2013-10-5, Mars Fu, first version. */ /* [Binary Search Algorithm] * Published by John Mauchly(1946) and D.H.Lehmer(1960). * * [Uniform Binary Search Algorithm] * Published by D.E.Knuth(1963) and A.K.Chandra(1971). */ #include "stdafx.h" #include "binary_search.h" #include "quicksort.h" int do_binary_search(void *key, void *src, int src_sz, int n, cmp_func cmp) { int li,ri,i; char *p; F_S(); if (key == NULL || src == NULL || cmp == NULL) return 0; if (src_sz <= 0 || n <= 0) return 0; li = 1; ri = n; while (li <= ri) { i = ((li + ri) >> 1); p = (char*)src + (i-1) * src_sz; if (cmp(key, p) < 0) { ri = i - 1; } else if (cmp(key, p) > 0) { li = i + 1; } else { goto END; } } return 0; END: F_E(); return i; } int do_uniform_binary_search(void *key, void *src, int src_sz, int n, cmp_func cmp) { int i,m; char *p; F_S(); if (key == NULL || src == NULL || cmp == NULL) return 0; if (src_sz <= 0 || n <= 0) return 0; i = (n + 1) / 2; m = n / 2; while (1) { p = (char*)src + (i-1) * src_sz; if (cmp(key, p) < 0) { if (m == 0) return 0; i -= ((m + 1) / 2); } else if (cmp(key, p) > 0) { if (m == 0) return 0; i += ((m + 1) / 2); } else { goto END; } m = m / 2; } return 0; END: F_E(); return i; } int do_uniform_binary_search_2(void *key, void *src, int src_sz, int n, cmp_func cmp) { int i,j,k,h,m; char *p; int n2; F_S(); if (key == NULL || src == NULL || cmp == NULL) return 0; if (src_sz <= 0 || n <= 0) return 0; /* formula: * h(j) = (n + 2^(j-1)) / (2^j), where 1 <= j <= (int)lg(n) + 2. */ n2 = 2; m = (int)(log((double)n) / log((double)n2)) + 2; for (i = (n + 1) / 2, j = 1, k = 2; j < m; ++j, k <<= 1) { h = (n + k) / (k << 1); p = (char*)src + (i-1) * src_sz; if (cmp(key, p) < 0) { if (h == 0) return 0; i -= h; } else if (cmp(key, p) > 0) { if (h == 0) return 0; i += h; } else { goto END; } } return 0; END: F_E(); return i; } #ifdef BINARY_SEARCH_DEBUG int int_cmp(void* lv, void* rv) { int tmp_lv, tmp_rv; tmp_lv = *(int*)lv; tmp_rv = *(int*)rv; return (tmp_lv - tmp_rv); } static void exchange_int_item(void* lv, void* rv) { int tmp_lv, tmp_rv; tmp_lv = *(int*)lv; tmp_rv = *(int*)rv; *(int*)lv = *(int*)rv; *(int*)rv = tmp_lv; } int main(int argc, char* argv[]) { int i; int cnt; int ret; int int_items[16] = { 503, 87, 512, 61, 908, 170, 897, 275, 653, 426, 154, 509, 612, 677, 765, 703 }; int key; debug("[Debug binary search].. \r\n"); cnt = sizeof(int_items)/sizeof(int_items[0]); debug("src database:\r\n----\r\n"); for (i = 0; i < cnt; ++i) { debug("%d ", int_items[i]); } debug("\r\n"); ret = do_quick_sort((void*)int_items, sizeof(int), cnt, int_cmp, exchange_int_item, NULL); if (!ret) { debug("failed. \r\n"); goto END; } debug("src database sorted:\r\n----\r\n"); for (i = 0; i < cnt; ++i) { debug("%d ", int_items[i]); } debug("\r\n"); debug("\r\n----\r\n"); key = int_items[0]; debug("search key %d... \r\n", key); ret = do_binary_search(&key, int_items, sizeof(int), cnt, int_cmp); if (!ret) debug("not found.\r\n"); ret = do_uniform_binary_search(&key, int_items, sizeof(int), cnt, int_cmp); if (!ret) debug("not found.\r\n"); ret = do_uniform_binary_search_2(&key, int_items, sizeof(int), cnt, int_cmp); if (!ret) debug("not found.\r\n"); debug("\r\n----\r\n"); key = int_items[cnt-1]; debug("search key %d... \r\n", key); ret = do_binary_search(&key, int_items, sizeof(int), cnt, int_cmp); if (!ret) debug("not found.\r\n"); ret = do_uniform_binary_search(&key, int_items, sizeof(int), cnt, int_cmp); if (!ret) debug("not found.\r\n"); ret = do_uniform_binary_search_2(&key, int_items, sizeof(int), cnt, int_cmp); if (!ret) debug("not found.\r\n"); debug("\r\n----\r\n"); key = int_items[cnt/2]; debug("search key %d... \r\n", key); ret = do_binary_search(&key, int_items, sizeof(int), cnt, int_cmp); if (!ret) debug("not found.\r\n"); ret = do_uniform_binary_search(&key, int_items, sizeof(int), cnt, int_cmp); if (!ret) debug("not found.\r\n"); ret = do_uniform_binary_search_2(&key, int_items, sizeof(int), cnt, int_cmp); if (!ret) debug("not found.\r\n"); debug("\r\n----\r\n"); key = 12345; debug("search key %d... \r\n", key); ret = do_binary_search(&key, int_items, sizeof(int), cnt, int_cmp); if (!ret) debug("not found.\r\n"); ret = do_uniform_binary_search(&key, int_items, sizeof(int), cnt, int_cmp); if (!ret) debug("not found.\r\n"); ret = do_uniform_binary_search_2(&key, int_items, sizeof(int), cnt, int_cmp); if (!ret) debug("not found.\r\n"); debug("\r\n"); debug("[Debug binary search]..done. \r\n"); END: while (1); return 1; } #endif /* BINARY_SEARCH_DEBUG */
#ifndef __BINARY_SEARCH_H__ #define __BINARY_SEARCH_H__ #define BINARY_SEARCH_DEBUG typedef int(*cmp_func)(void*,void*); int do_binary_search(void *key, void *src, int src_sz, int n, cmp_func cmp); int do_uniform_binary_search(void *key, void *src, int src_sz, int n, cmp_func cmp); int do_uniform_binary_search_2(void *key, void *src, int src_sz, int n, cmp_func cmp); #endif /* __BINARY_SEARCH_H__ */
#pragma once #include <windows.h> #ifdef _WIN32 #define msleep(x) Sleep(x) #endif #include <stdio.h> #include <tchar.h> #include <stdlib.h> #include <malloc.h> #include <string.h> #include <math.h> #define MY_DEBUG #ifdef MY_DEBUG #define debug printf #else #define debug(x,argc, __VA_ARGS__) ; #endif /* MY_DEBUG */ #define F_S() debug("[%s]..\r\n", __FUNCTION__) #define F_E() debug("[%s]..done. \r\n", __FUNCTION__)
Enjoy~
Mars
October 5, 2013