Foundation: Binary Search

/* 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].. 
");

	cnt = sizeof(int_items)/sizeof(int_items[0]);

	debug("src database:
----
");
	for (i = 0; i < cnt; ++i) {
		debug("%d ", int_items[i]);
	}
	debug("
");

	ret = do_quick_sort((void*)int_items, sizeof(int), cnt, 
		                 int_cmp, exchange_int_item, NULL);
	if (!ret) {
		debug("failed. 
");
		goto END;
	}

	debug("src database sorted:
----
");
	for (i = 0; i < cnt; ++i) {
		debug("%d ", int_items[i]);
	}
	debug("
");

	debug("
----
");
	key = int_items[0];
	debug("search key %d... 
", key);
    ret = do_binary_search(&key, int_items, sizeof(int), cnt, int_cmp);
	if (!ret) debug("not found.
");
    ret = do_uniform_binary_search(&key, int_items, sizeof(int), cnt, int_cmp);
	if (!ret) debug("not found.
");
    ret = do_uniform_binary_search_2(&key, int_items, sizeof(int), cnt, int_cmp);
	if (!ret) debug("not found.
");

	debug("
----
");
	key = int_items[cnt-1];
	debug("search key %d... 
", key);
    ret = do_binary_search(&key, int_items, sizeof(int), cnt, int_cmp);
	if (!ret) debug("not found.
");
    ret = do_uniform_binary_search(&key, int_items, sizeof(int), cnt, int_cmp);
	if (!ret) debug("not found.
");
    ret = do_uniform_binary_search_2(&key, int_items, sizeof(int), cnt, int_cmp);
	if (!ret) debug("not found.
");

	debug("
----
");
	key = int_items[cnt/2];
	debug("search key %d... 
", key);
    ret = do_binary_search(&key, int_items, sizeof(int), cnt, int_cmp);
	if (!ret) debug("not found.
");
    ret = do_uniform_binary_search(&key, int_items, sizeof(int), cnt, int_cmp);
	if (!ret) debug("not found.
");
    ret = do_uniform_binary_search_2(&key, int_items, sizeof(int), cnt, int_cmp);
	if (!ret) debug("not found.
");

	debug("
----
");
	key = 12345;
	debug("search key %d... 
", key);
    ret = do_binary_search(&key, int_items, sizeof(int), cnt, int_cmp);
	if (!ret) debug("not found.
");
    ret = do_uniform_binary_search(&key, int_items, sizeof(int), cnt, int_cmp);
	if (!ret) debug("not found.
");
    ret = do_uniform_binary_search_2(&key, int_items, sizeof(int), cnt, int_cmp);
	if (!ret) debug("not found.
");

	debug("
");

	debug("[Debug binary search]..done. 
");
    
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]..
", __FUNCTION__)
#define F_E() debug("[%s]..done. 
", __FUNCTION__)


Enjoy~

Mars微笑

October 5, 2013

原文地址:https://www.cnblogs.com/keanuyaoo/p/3353237.html