# 1.查找

## 1.1 线性表查找

（1）顺序查找

``````public class SearchDemo1 {

public static void main(String[] args) {

//        给定分数数组
int[] scoreArr = {

89, 45, 78, 45, 100, 98, 86, 100, 65};
//        给定要查找的分数
int score = 100;
//        完成查找
int index = -1;
for (int i = 0; i < scoreArr.length; i++) {

if (scoreArr[i] == score){

index = i;
break;
} }
//        输出结果
if (index == -1) {

System.out.println("该分数不存在");
}else {

System.out.println(score+"的索引是"+index);
} } }
``````

（2）折半查找：顺序结构、按照关键字有序
①非递归

``````public class SearchDemo2 {

public static void main(String[] args) {

//        给定数组
int[] arr = {

1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
//给定要查找的值
int key = 9;
//        进行折半二分查找
int index = binarySearch(arr, key);
//        输出结果
if (index == -1) {

System.out.println("该分数不存在");
} else {

System.out.println(key + "的索引是" + index);
} }
//    不使用递归
public static int binarySearch(int[] array, int key) {

//        指定low和high
int low = 0;
int high = array.length - 1;
//        折半查找
while (low <= high) {

//            求mid
int mid = (low + high) / 2;
//            判断是否等于
if (key == array[mid]) {

return mid;
} else if (key < array[mid]) {

high = mid - 1;
} else {

low = mid + 1;
}
}
return -1;
} }
``````

②递归

``````public class SearchDemo3 {

public static void main(String[] args) {

//        给定数组
int[] arr = {

1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
//给定要查找的值
int key = 10;
//        进行折半二分查找
int index = binarySearch(arr, key);
//        输出结果
if (index == -1) {

System.out.println("该分数不存在");
} else {

System.out.println(key + "的索引是" + index);
}
}
//   使用递归
public static int binarySearch(int[] array, int key) {

//指定low和high
int low = 0;
int high = array.length - 1;
return binarySearch(array, key, low, high);
}
public static int binarySearch(int[] array, int key, int low, int high) {

//  递归结束的条件
if (low > high) {

return -1;
}
int mid = (low + high) / 2;
if (key == array[mid]) {

return mid;
} else if (key < array[mid]) {

return binarySearch(array, key, low, mid - 1);
} else {

return binarySearch(array, key, mid + 1, high);
} } }
``````

## 1.2 查找树

### 1.2.1 二叉查找/搜索/排序树 BST

（1）或者是一棵空树
（2）或者是具有下列性质的二叉树
①若它的左子树不为空，则左子树上所有结点的值均小于它的根结点的值
②若它的右子树上所有结点的值均大于它的根结点的值
③它的左、右子树也分别为二叉排序树

### 1.2.2 平衡二叉树

（1）它是一棵空树
（2）或它的左右两个子树的高度差(平衡因子)的绝对值不超过1，

①平衡因子：结点的平衡因子是结点的左子树的高度减去右子树的高度
②平衡二叉树：每个结点的平衡因子都为1、-1、0的二叉排序树。或者说每个结点的左右子树的高度

（3）二叉树的目的是为了减少二叉查找树层次，提高查找速度

### 1.2.3 红黑树

R-B Tree,全称是Red-Black Tree,又称为“红黑树”，它是一种平衡二叉树。红黑树的每个结点上都有存储位表示结点的颜色，可以是红或黑。

（1）每个结点或者是黑色，或者是红色。
（2）根结点是黑色
（3）每个叶子结点是黑色(注意:这里叶子结点，是指为空的叶子结点)
（4）如果一个结点是红色，则它的子节点必须是黑色的。
（5）从一个结点到该结点的子孙结点的所有路径上包含相同数目的黑结点。

### 1.2.5 B+树

（1）所有的数据都在最下面一层
（2）在B-树(即B树)基础上，为叶子结点增加链表指针，所有关键字都在叶子结点中出现，非叶子结点作为叶子结点的索引；B+树总是到叶子结点才命中。

## 1.3 哈希表查找

### 1.3.1 哈希表的结构和特点

（1）hash table(哈希表) 也叫散列表
（2）特点：快
（3）结构有多种，

（4）主结构：顺序表
（5）每个顺序表的结点再单独引出一个链表

### 1.3.2 哈希表是如何添加数据的

（1）计算哈希码(调用hashCode(),结果是一个int值，整数的哈希码取自身即可)
（2）计算在哈希表中的存储位置（根据hashcode计算出hash值）
hashcode是一个整数，我们需要将它转化成[0, 数组长度-1]的范围。我们要求转化后的hash值尽量均匀地分布在[0,数组长度-1]这个区间，减少“hash冲突”
① 一种极端简单和低下的算法是：hash值 = hashcode/hashcode;

②一种简单和常用的算法是(相除取余算法)：hash值 = hashcode%数组长度

（3）存入哈希表：

### 1.3.4 hashCode和equals的作用

（1）hashCode()：用于计算哈希码，是一个整数，根据哈希码可以计算出数据在哈希表中的存储位置。
（2）equals()：添加时出现了冲突，需要通过equals进行比较，判断是否相同

### 1.3.5 各种类型数据的哈希码如何获取

（1）Integer

``````// int就是取自身
public static int hashCode(int value) {

return value;
}
``````

（2）Double

``````  public static int hashCode(double value) {

long bits = doubleToLongBits(value);
return (int)(bits ^ (bits >>> 32));
}
``````

（3）String

`````` public int hashCode() {

int h = hash;
if (h == 0 && value.length > 0) {

char val[] = value;
for (int i = 0; i < value.length; i++) {

h = 31 * h + val[i];
}
hash = h;
}
return h;
}
``````

# 2.排序

## 2.1 排序的介绍

（1）什么是排序

（2）内部排序和外部排序
①整个排序过程在内存储器中进行，称为内部排序
②待排序元素数量太大，以至于内存储器无法全部容纳全部数据，排序需要借助外部存储设备才能完成，这类

（3）稳定排序和不稳定排序
①假设Ri=Rj,若在排序之前Ri就在Rj之前，经过排序之后Ri仍在Rj之前，则称所用的排序方法是稳定的。
②否则，当相同关键字元素的前后关系在排序中发生变化，则称所用的排序方法是不稳定的
(在某些场合可能对排序有稳定性的要求，例如学生按成绩排序，分数相同时要求学号小的在前)

## 2.2 快速排序

（1）先从数列中取出一个数作为基准数(简单起见可以取第一个数)
（2）分区过程，将比这个数大的数全部放到它的右边，小于或等于它的数全部放到它的左边（分区）
（3）再对左右区间重复第一步、第二步，直到各区间只有一个数（递归）