查找与哈希表
二分查找 O ( log ( N ) ) O(\log(N)) O(log(N))
前提:单调性
取中间,舍去。
核心:将原问题规模减半。
#include<stdio.h>
int binary_search(int *arr, int n, int x) {
int head = 0, tail = n -1, mid;
while (head <= tail) {
mid = (head + tail) >> 1;
if (arr[mid] == x) return mid;
if (arr[mid] < x) head = mid + 1;
else tail = mid - 1;
}
return -1;
}
int main () {
int arr[100] = {0}, n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", arr + i);
}
int x;
while (~scanf("%d", &x)) {
printf("%d\n", binary_search(arr, n, x));
}
return 0;
}
特殊情况1
111111111000000000
虚拟头指针
#include<stdio.h>
int binary_search2(int *arr, int n) {
int head = -1, tail = n - 1, mid;
while (head < tail) {
mid = (head + tail + 1) >> 1; //向上取整
if (arr[mid] == 1) head = mid;
else tail = mid - 1;
}
return head;
}
int main () {
int arr[100] = {0}, n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", arr + i);
}
printf("%d\n", binary_search2(arr, n));
return 0;
}
特殊情况2
0000011111 找第一个1的位置
#include<stdio.h>
int binary_search1(int *arr, int n) {
int head = 0, tail = n, mid;
while (head < tail) {
mid = (head + tail) >> 1;
if (arr[mid] == 1) tail = mid;
else head = mid + 1;
}
return head == n ? -1 : head;
}
int main () {
int arr[100] = {0}, n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", arr + i);
}
printf("%d\n", binary_search1(arr, n));
return 0;
}
三分查找
M1 : 1/3
M2 : 2/3
可求解凹凸函数的极值点
将规模缩小1/3
哈希表
任意类型到任意类型的映射
连续的存储空间 哈希函数 映射成整型 后用顺序表访问
哈希表的冲突处理方法
映射的冲突
- 开放定值法
冲突后往后放一个;
二次探测法:放在 2 2 2^2 22后
- 拉链法
用链表处理冲突
- 再哈希法
多个哈希函数处理
- 建立公共溢出区
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct Node {
char *str;
struct Node *next;
} Node;
typedef struct HashTable {
Node **data;
int size;
} HashTable;
Node *init_node(char *str, Node *head) {
Node *p = (Node *)malloc(sizeof(Node));
p->str = strdup(str);
p->next = head;
return p;
}
HashTable *init_hashtable(int n) {
HashTable *h = (HashTable *)malloc(sizeof(HashTable));
h->size = n << 1;
h->data = (Node **)calloc(h->size, sizeof(Node *));
return h;
}
int BKDRHash(char *str) {
int seed = 31, hash = 0;
for (int i = 0; str[i]; i++) hash = hash *seed + str[i];
return hash & 0x7fffffff; //转换为正数
}
int insert(HashTable *h, char *str) {
int hash = BKDRHash(str);
int ind = hash % h->size;
h->data[ind] = init_node(str, h->data[ind]);
}
int search(HashTable *h, char *str) {
int hash = BKDRHash(str);
int ind = hash % h->size;
Node *p = h->data[ind];
while (p && strcmp(p->str, str)) p = p->next;
return p != NULL;
}
void clear_node(Node *node) {
if (node == NULL) return ;
Node *p = node, *q;
while (p) {
q = p->next;
free(p->str);
free(p);
p = q;
}
return ;
}
void clear(HashTable *h) {
if (h == NULL) return ;
for (int i = 0; i < h->size; i++) {
clear_node(h->data[i]);
}
free(h->data);
free(h);
return ;
}
int main() {
int op;
#define MAX_N 100
char str[MAX_N + 5] = {0};
HashTable *h = init_hashtable(MAX_N + 5);
while (~scanf("%d%s", &op, str)) {
switch (op) {
case 0:
printf("insert %s to HashTable\n", str);
insert(h, str);
break ;
case 1:
printf("search %s from HashTable result = %d\n", str, search(h, str));
break ;
}
}
#undef MAX_N
clear(h);
return 0;
}