/*!
\author LiuBao
\date 2011/4/12
\brief 微软实习面试题
*/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define ARRAY_SIZE(array) \
(sizeof(array) / sizeof(array[0]))
typedef struct BTree BTree;
struct BTree
{
BTree *left;
BTree *right;
int value;
};
typedef struct Node Node;
struct Node
{
Node *next;
int value;
};
/*!
考察算法1
原意是要用最快方法,在可重复元素的排序数组中,寻找一个值的出现次数,
这个问题可以归结为用最快方法寻找该值的出现在数组中的最小下标。由此,
衍生出本题。
在可重复元素排序数组array中,dest出现的数组下标最小值。
1、若dest大于数组最大值,返回n
2、若dest小于等于数组最小值,返回0
3、否则,若dest在数组中不存在,返回大于dest的元素的数组下标最小值
\note 真不知道如此不确定性为的函数有啥用?
\param array 可能具有可重复元素的排序数组
\param n 数组元素个数
\param dest 查找元素值
\return 查找结果(下标值)
*/
int low_bound(const int array[], int n, int dest)
{
int retVal = -1;
if(array[n - 1] < dest)
retVal = n;
else if(array[0] >= dest)
retVal = 0;
else
{
int low = 0;
int high = n - 1;
int mid;
while(low <= high)
{
mid = (low + high) / 2;
if(array[mid] < dest)
low = mid + 1;
else
high = mid - 1;
}
retVal = high + 1;
}
return retVal;
}
/*!
辅助函数1
用int数组内元素创建一个单向链表
\param array 用于创建链表的数组
\param n 数组元素个数
\return 若创建成功,返回链表头指针;否则返回NULL
*/
Node *create_link(const int *array, int n)
{
Node *head = NULL;
Node **p = &head;
while(n-- && (*p = malloc(sizeof(Node))))
{
(*p)->value = *array++;
p = &(*p)->next;
}
*p = NULL;
return head;
}
/*!
考察算法2
查找单向链表head的倒数第n个节点,最末个节点记为倒数第1个
\param head 查找单向链表的头指针
\param n 查找倒数节点序号
\return 查找成功返回该节点指针;否则返回NULL
*/
Node *find_backwards(Node *head, int n)
{
Node *pre = head;
while(n-- && head) head = head->next;
while(head) pre = pre->next, head = head->next;
return (!n && head) ? NULL : pre;
}
/*!
辅助函数2
插入节点到排序二叉树中
\param root 排序二叉树根节点,可以为NULL
\param val 插入的值
\return 返回成功插入的节点指针
*/
BTree *insert_node(BTree *root, int val)
{
BTree **p = &root;
while(*p)
{
if((*p)->value < val)
p = &(*p)->right;
else
p = &(*p)->left;
}
if((*p = calloc(sizeof(BTree), 1)))
(*p)->value = val;
return *p;
}
/*!
考察算法3
验证一颗树是否为排序二叉树
\param root 树根
\return 若是排序二叉树,返回真;否则返回假
*/
int is_sort_tree(BTree *root)
{
static int pre = INT_MIN;
static int success = 1;
if(root && success)
{
is_sort_tree(root->left);
if(pre <= root->value)
pre = root->value;
else
success = 0;
is_sort_tree(root->right);
}
return success;
}
int main()
{
int array[] = {2, 2, 3, 6, 6, 8, 9, 9};
/* 测试算法1 */
printf("low bound: %d\n", low_bound(array, ARRAY_SIZE(array), 7));
/* 测试算法2 */
{
Node *link = create_link(array, ARRAY_SIZE(array));
Node *found;
if((found = find_backwards(link, 6)))
printf("found backwards: %d\n", found->value);
}
/* 测试算法3 */
{
int array[] = {4, 3, 5, 7, 6, 9};
BTree *root = insert_node(NULL, 6); //创建树根
int i;
for(i = 0; i < ARRAY_SIZE(array); ++i) //创建排序二叉树
insert_node(root, array[i]);
insert_node(root->left, 7); //可以用来破坏排序二叉树
printf("test result : %d\n", is_sort_tree(root));
}
return 0;
}