1.查找算法概述:
- 顺序查找
- 二分查找
- 分块查找
- 二叉排序树查找
- 哈希表查找
2.顺序查找:
java实现:
public int seqSearch(int[] data, int key){
int index;
for(index = 0; index < data.length; index++){
if(key == data[index]){
return index;
}
}
return -1;
}
3.二分查找:
java实现:
public int binSearch(int[] data, int key){
int low = 0, high = data.length - 1, mid;
while (high >= low){
mid = (low + high) / 2;
if(key == data[mid]){
return mid;
}
else if(key > data[mid]){
low = mid + 1;
}else {
high = mid - 1;
}
}
return -1;
}
4.分块查找:
java实现:
static class BlockInfo{
int blockBeginIndex; //块的起始下标
int blockEndIndex; //块的结束下标
int blockMaxValue; //块中最大关键字
}
public int blockSearch(int[] data, int key){
BlockInfo[] blocks = getBlockArray(data);
int blockindex = -1;
for(int i = 0; i < blocks.length - 1; i++){
if(key >= blocks[i].blockMaxValue && key <= blocks[i + 1].blockMaxValue){
blockindex = i + 1;
break;
}
}
if(blockindex != -1){
int index;
for(index = blocks[blockindex].blockBeginIndex; index < blocks[blockindex].blockEndIndex; index++){
if(key == data[index]){
return index;
}
}
}
return -1;
}
//创建分块查找的索引表
private BlockInfo[] getBlockArray(int[] data) {
int length = data.length;
int n = (int)Math.sqrt(length);
int m = (int)length / n;
BlockInfo[] blocks = new BlockInfo[m];
for(int i = 0; i < m; i++){
BlockInfo block = new BlockInfo();
block.blockBeginIndex = i * n;
if(i * n + n - 1 < length -1){
block.blockEndIndex = i * n + n -1;
}else {
block.blockEndIndex = length - 1;
}
int maxValue = data[block.blockBeginIndex];
for(int j = block.blockBeginIndex; j < block.blockEndIndex; j++){
if(maxValue < data[j]){
maxValue = data[j];
}
}
block.blockMaxValue = maxValue;
blocks[i] = block;
}
return blocks;
}
5.二叉排序树查找:
java实现:
public class BinarySearchTree {
//树结点
private static class TreeNode{
int key;
TreeNode left; //左子树
TreeNode right; //右子树
TreeNode(int key, TreeNode left, TreeNode right){
this.key = key;
this.left = left;
this.right = right;
}
}
private TreeNode root; //根
public BinarySearchTree(){
root = null;
}
//树置空
public void makeEmpty(){
root = null;
}
//判断树是否为空
public boolean isEmpty(){
return root == null;
}
//是否包含某个元素
public boolean search(int key){
return search(key, root);
}
public boolean search(int key, TreeNode t){
if(t == null){
return false;
}
if(key < t.key){
return search(key, t.left);
}
else if(key > t.key){
return search(key, t.right);
}
return true;
}
//给树添加一个新的结点
public void insert(int key){
root = insert(key, root);
}
public TreeNode insert(int key, TreeNode t){
if(t == null){
return new TreeNode(key,null, null);
}
if(key < t.key){
t.left = insert(key, t.left);
}
else if(key > t.key){
t.right = insert(key, t.right);
}
return t;
}
//移除一个结点
public void remove(int key){
root = remove(key, root);
}
private TreeNode remove(int key, TreeNode t){
if(t == null){
return null;
}
if(key < t.key){
t.left = remove(key, t.left);
}
else if(key > t.key){
t.right = remove(key, t.right);
}
else if(t.left != null && t.right != null){
t.key = findMin(t.right).key;
t.right = remove(t.key, t.right);
}else {
t = (t.left != null) ? t.left : t.right;
}
return t;
}
//查找树中最小值
public int findMin(){
if(isEmpty()){
return Integer.MIN_VALUE;
}
return findMin(root).key;
}
private TreeNode findMin(TreeNode t){
if(t == null){
return null;
}
if(t.left == null){
return t;
}
return findMin(t.left);
}
//输出树中元素
public void printTree(){
if(isEmpty()){
System.out.println("Empty tree");
}else {
printTree(root);
}
System.out.println();
}
private void printTree(TreeNode t){
if(t != null){
printTree(t.left);
System.out.print(t.key + " ");
printTree(t.right);
}
}
}
测试类:
public class TestBinarySearchTree {
public static void main(String[] args){
BinarySearchTree bst = new BinarySearchTree();
bst.insert(70);
bst.insert(30);
bst.insert(40);
bst.insert(10);
bst.insert(80);
bst.insert(20);
bst.insert(90);
bst.insert(100);
bst.insert(75);
bst.insert(60);
bst.insert(45);
System.out.println("遍历二叉排序树");
bst.printTree();
System.out.println("hava 80 -->" + bst.search(80));
System.out.println("hava 65 -->" + bst.search(65));
}
}
结果:
6.哈希表查找:
- 哈希表在关键字和存储位置之间建立了对应关系,理想情况下无须比较关键字就可找到待查关键字,查找的期望时间为O(1).
java实现:
public class HashTableSearch {
/*哈希结点*/
private static class Node{
int key; //链表中的键
Node next; //下一个同义词
}
/*在哈希表中查找关键字key*/
public boolean HashSearch(int[] data, int key){
int p = 1;
//寻找小于或等于最接近表长的素数
for(int i = data.length; i > 1; i--){
if(isPrimes(i)){
p = i;
break;
}
}
//构建哈希表
Node[] hashtable = createHashTable(data, p);
//查找key是否在哈希表中
int k = key % p;
Node cur = hashtable[k];
while (cur != null && cur.key != key){
cur = cur.next;
}
if(cur == null){
return false;
}else {
return true;
}
}
/*用求余,链表法构建哈希表*/
public Node[] createHashTable(int[] data, int p){
Node[] hashtable = new Node[p];
int k; //哈希函数计算的单元地址
for(int i = 0; i < data.length; i++){
Node node = new Node();
node.key = data[i];
node.next = null;
k = data[i] % p;
if(hashtable[k] == null){
hashtable[k] = node;
}else {
Node cur = hashtable[k];
while (cur.next != null){
cur = cur.next;
}
}
}
return hashtable;
}
/*判断是否是一个质数*/
public boolean isPrimes(int n){
for(int i = 2; i < Math.sqrt(n); i++){
if(n % i == 0){
return false;
}
}
return true;
}
}
测试:
public class TestHashTableSearch {
public static void main(String[] args){
int[] data = {70, 30, 40, 10, 80, 20, 90, 100, 75, 60, 45};
HashTableSearch search = new HashTableSearch();
if(search.HashSearch(data, 80)){
System.out.println("在数字列表中存在关键字80");
}else {
System.out.println("在数字列表中不存在关键字80");
}
if(search.HashSearch(data, 65)){
System.out.println("在数字列表中存在关键字65");
}else {
System.out.println("在数字列表中不存在关键字65");
}
}
}
结果:
参考书目:数据结构(Java版)