Merge pull request #136 from jin13417/master

add for 二分查找
This commit is contained in:
wangzheng0822 2018-11-05 10:47:00 +08:00 committed by GitHub
commit 5e21552151
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 621 additions and 0 deletions

View File

@ -0,0 +1,53 @@
/*************************************************************************
> File Name: sqrt.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-31
> Desc:
************************************************************************/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
/*求解精度设置*/
#define E 0.000001
double mybsearch(double num)
{
double start = 1.0;
double end = num;
double mid = 0.0;
while(1)
{
mid = (start + end)/2;
if(((mid*mid - num) <= E) && ((mid*mid - num) >= -E))
{
return mid;
}
if ((mid*mid - num) > E)
{
end = mid;
}
else
{
start = mid;
}
}
return 0;
}
int main()
{
double num = 0.0;
/*这里需要注意double的输入方式*/
scanf("%lf",&num);
printf("\r\n num %lf的平方根是%lf",num,mybsearch(num));
return 0;
}

190
c-cpp/16_bsearch/bsearch.c Normal file
View File

@ -0,0 +1,190 @@
/*************************************************************************
> File Name: bsearch.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-21
> Desc:
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
/*二分查找算法的变形问题
*1
*2
*3
*4
* */
/*1、查找第一个等于给定数值的元素*/
int mybsearch_1(int a[],int size,int value)
{
int mid = 0;
int left = 0;
int right = size - 1;
while(left <= right)
{
/*防止size数量太大是left + right数据翻转导致问题*/
mid = left + ((right - left)>>1);
if (a[mid] < value)
{
left = mid + 1;
}
else if (a[mid] > value)
{
right = mid - 1;
}
else
{
if ((mid == 0) || (a[mid - 1] != value))
{
return mid;
}
else
{
right = mid - 1;
}
}
}
return -1;
}
/*2、查找最后一个等于给定数值的元素*/
int mybsearch_2(int a[],int size,int value)
{
int mid = 0;
int left = 0;
int right = size - 1;
while(left <= right)
{
/*防止size数量太大是left + right数据翻转导致问题*/
mid = left + ((right - left)>>1);
if (a[mid] < value)
{
left = mid + 1;
}
else if (a[mid] > value)
{
right = mid - 1;
}
else
{
if ((mid == (size - 1)) || (a[mid + 1] != value))
{
return mid;
}
else
{
left = mid + 1;
}
}
}
return -1;
}
/*3、查找第一个大于等于给定数值的元素*/
int mybsearch_3(int a[],int size,int value)
{
int mid = 0;
int left = 0;
int right = size - 1;
while(left <= right)
{
/*防止size数量太大是left + right数据翻转导致问题*/
mid = left + ((right - left)>>1);
if (a[mid] < value)
{
left = mid + 1;
}
else
{
/*a[mid] >= value 当mid==0 或者a[mid-1] > value 说明是第一个大于等于value*/
if ((mid == 0) || (a[mid - 1] < value))
{
return mid;
}
else
{
right = mid - 1;
}
}
}
return -1;
}
/*4、查找第一个小于等于给定数值的元素*/
int mybsearch_4(int a[],int size,int value)
{
int mid = 0;
int left = 0;
int right = size - 1;
while(left <= right)
{
/*防止size数量太大是left + right数据翻转导致问题*/
mid = left + ((right - left)>>1);
if (a[mid] > value)
{
right = mid - 1;
}
else
{
/*a[mid] <= value 时当前mid == size -1 数组中最大的数值;
* a[mid + 1] vlauemid就第一个小于等于value*/
if ((mid == (size - 1)) || (a[mid + 1] > value))
{
return mid;
}
else
{
left = mid + 1;
}
}
}
return -1;
}
int main()
{
int a[10] = {5,6,6,9,10,11,11,22,33,33};
int data = 0;
int i = 0;
int res =0;
printf("\r\n");
for(i = 0; i < 10 ; i++)
{
printf("%d ",a[i]);
}
printf("\r\n");
printf("\r\n输入一个整数");
scanf("%d",&data);
res = mybsearch_1(a,10,data);
printf("第一个等于data[%d],下标是%d",data,res);
printf("\r\n输入一个整数");
scanf("%d",&data);
res = mybsearch_2(a,10,data);
printf("最后一个等于data[%d],下标是%d",data,res);
printf("\r\n输入一个整数");
scanf("%d",&data);
res = mybsearch_2(a,10,data);
printf("第一个大于等于data[%d],下标是%d",data,res);
printf("\r\n输入一个整数");
scanf("%d",&data);
res = mybsearch_2(a,10,data);
printf("第一个小等于data[%d],下标是%d",data,res);
return;
}

View File

@ -0,0 +1,345 @@
/*************************************************************************
> File Name: skiplist.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-31
> Desc:
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include"./skiplist.h"
/*创建node节点*/
node* skip_list_create_node(int level,int key,int value)
{
node * tmp = NULL;
tmp =(node *)malloc(sizeof(node) + level*sizeof(node *));
assert(tmp != NULL);
memset(tmp,0,sizeof(node) + level*sizeof(node*));
tmp->key = key;
tmp->value = value;
tmp->max_level = level;
return tmp;
}
/*创建跳表的表头max_level层数*/
skiplist * skip_list_create(int max_level)
{
int i = 0;
skiplist * list = NULL;
list = (skiplist *)malloc (sizeof(skiplist));
assert(list != NULL);
list->level = 1;
list->count = 0;
list->head = skip_list_create_node(max_level,0,0);
if(list->head == NULL)
{
free(list);
return NULL;
}
return list;
}
/*skiplist 销毁*/
void skip_list_destory(skiplist * list)
{
int i = 0;
node * tmp = NULL;
if((list == NULL) || (list->head == NULL))
{
return;
}
while(list->head->next[0] != NULL)
{
tmp = list->head->next[0];
list->head->next[0] = tmp->next[0];
free(tmp);
}
free(list);
return;
}
/*插入元素获得层数,是随机产生的*/
int skip_list_level(skiplist * list)
{
int i = 0;
int level = 1;
for (i = 1; i < list->head->max_level; i++)
{
if ((rand()%2) == 1)
{
level++;
}
}
return level;
}
int skip_list_insert(skiplist *list,int key,int value)
{
int i = 0;
int level = 0;
node **update = NULL;/*用来更新每层的指针*/
node *tmp = NULL;
node *prev = NULL;
if (list == NULL)
{
return 1;
}
/*申请update空间用于保存每层的指针*/
update = (node **)malloc(sizeof(node *)*list->head->max_level);
if (update == NULL)
{
return 2;
}
/*逐层查询节点的*/
prev = list->head;
for (i = (list->level -1); i >= 0; i--)
{
/*初始化每level层的头指针*/
while(((tmp = prev->next[i]) != NULL) && (tmp->key < key))
{
prev = tmp;
}
update[i] = prev;
}
/*当前key已经存在返回错误*/
if ((tmp!= NULL) && (tmp->key == key))
{
return 3;
}
/*获取插入元素的随机层数,并更新跳表的最大层数*/
level = skip_list_level(list);
/*创建当前数据节点*/
tmp = skip_list_create_node(level,key,value);
if (tmp == NULL)
{
return 4;
}
/*更新最大层数*/
if (level > list->level)
{
for (i = list->level;i < level; i ++)
{
update[i] = list->head;
}
list->level = level;
}
/*逐层更新节点的指针*/
for(i = 0; i < level; i++)
{
tmp->next[i] = update[i]->next[i];
update[i]->next[i] = tmp;
}
list->count++;
return 0;
}
int skip_list_delete(skiplist * list, int key ,int *value)
{
int i = 0;
node **update = NULL;/*用来更新每层的指针*/
node *tmp = NULL;
node *prev = NULL;
if ((list == NULL) && (value == NULL)&& (list->count == 0))
{
return 1;
}
/*申请update空间用于保存每层的指针*/
update = (node **)malloc(sizeof(node *)*list->level);
if (update == NULL)
{
return 2;
}
/*逐层查询节点的*/
prev = list->head;
for (i = (list->level -1); i >= 0; i--)
{
/*初始化每level层的头指针*/
while(((tmp = prev->next[i]) != NULL) && (tmp->key < key))
{
prev = tmp;
}
update[i] = prev;
}
if ((tmp != NULL)
&& (tmp->key == key))
{
*value = tmp->value;
/*逐层删除*/
for(i = 0; i < list->level; i++)
{
if(update[i]->next[i] == tmp)
{
update[i]->next[i] = tmp->next[i];
}
}
free(tmp);
tmp = NULL;
/*更新level的层数*/
for (i = list->level - 1; i >= 0; i++)
{
if (list->head->next[i] == NULL )
{
list->level--;
}
else
{
break;
}
}
list->count--;
}
else
{
return 3;/*未找到节点*/
}
return 0 ;
}
/*查询当前key是否在跳表中如果存在返回查询的value数值不存在返回-1*/
int skip_list_search(skiplist *list,int key,int *value)
{
int i = 0;
node *prev = NULL;
node *tmp = NULL;
if((list == NULL) || (list->count == 0) || (value == NULL))
{
return 1;
}
prev = list->head;
for(i = list->level - 1; i >= 0; i--)
{
while(((tmp = prev->next[i]) != NULL) && (tmp->key <= key))
{
if (tmp->key == key)
{
*value = tmp->value;
return 0;
}
prev = tmp;
}
}
return -1;
}
void skip_list_dump(skiplist *list)
{
int i = 0;
node *ptmp = NULL;
printf("\r\n----------------------------------------------");
printf("\r\n skip list level[%d],count[%d]",list->level,list->count);
for(i = list->level - 1; i >= 0; i --)
{
ptmp = list->head->next[i];
printf("\r\n level[%d]:",i);
while(ptmp != NULL)
{
printf("%d-%d ",ptmp->key,ptmp->value);
ptmp = ptmp->next[i];
}
}
printf("\r\n----------------------------------------------");
return;
}
int main()
{
int res = 0;
int key = 0;
int value = 0;
skiplist *list = NULL;
list = skip_list_create(5);
assert(list != NULL);
while(1)
{
printf("\r\n 请输入key 和 value当key = 1000时退出输入");
scanf("%d%d",&key,&value);
if (key == 1000)
{
break;
}
res = skip_list_insert(list,key,value);
if (res != 0)
{
printf("\r\n skip list insert %d,failed,res=%d.",key,res);
}
}
skip_list_dump(list);
while(1)
{
printf("\r\n 通过key 查询value的数值当key = 1000时退出查询");
scanf("%d",&key);
if(key == 1000)
{
break;
}
res = skip_list_search(list,key,&value);
if (res != 0)
{
printf("\r\n skip list search %d,failed,res=%d.",key,res);
}
else
{
printf("\r\n skip list search %d,sucessful,value=%d.",key,value);
}
}
skip_list_dump(list);
while(1)
{
printf("\r\n 通过key 删除节点当key = 1000时退出删除");
scanf("%d",&key);
if(key == 1000)
{
break;
}
res = skip_list_delete(list,key,&value);
if (res != 0)
{
printf("\r\n skip list search %d,failed,res=%d.",key,res);
}
else
{
printf("\r\n skip list search %d,sucessful,value=%d.",key,value);
}
}
skip_list_dump(list);
skip_list_destory(list);
return 0;
}

View File

@ -0,0 +1,33 @@
/*************************************************************************
> File Name: skiplist.h
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-31
> Desc:
************************************************************************/
#ifndef __SKIP_LIST_H__
#define __SKIP_LIST_H__
typedef struct _node
{
int key; /*key是唯一的*/
int value; /*存储的内容*/
int max_level; /*当前节点最大层数*/
struct _node *next[0];/*level层链表结构*/
}node;
typedef struct _skiplist
{
int level;
int count;
node *head;
}skiplist;
/*根据当前结构体元素的地址,获取到结构体首地址*/
#define offsetof(TYPE,MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container(ptr,type,member) ({\
const typeof( ((type *)0)->member) *__mptr = (ptr);\
(type *) ( (char *)__mptr - offsetof(type,member));})
#endif