查找

1.查找表  是  由同一类型的数据元素 或者  记录 构成的集合

  关键字 是数据元素中某个数据项的值。    就是某一个字段

  主关键字,就相当于字段的id                  此关键字 非  id的字段

  次关键字,就相当非关键的字段

--------------------------------------------------

静态查找表:只作查找操作的查找表    表数据不会动

动态查找表:查找过程中,同时插入 查找表中  不存在的数据元素, 或者从查找表中删除  已存在的元素

例子:比如一个字典要收录一个词。 插入时,先看数据库中有没有改词,没有的话,再确认位置。

          删除某条数据,找到删除。           这就用到动态查找表

---------------------------------------------------

2.顺序查找表(线性查找)

@Test
    public void lineSearch(){
        int arr[] = {3,4,7,9,6,2,-1};
        int result = 0,key = 2;
        for(int i=0;i<arr.length;i++){
            if(arr[i]==key){
                result = i;
            }
        }
        System.out.println(result);
    }
    //优化
    @Test
    public void betterlineSearch(){
        int arr[] = {3,4,7,9,6,2,-1};
        int key=-1;
        arr[0] = key;
        int i=arr.length-1;
        for(;i>=0;i--){
            if(arr[i]==key){
                break;
            }
        }
        System.out.println(i);
    }

 3.有序表查找

3.1 折半查找

/**
     * 有序查找 折半
     */
    @Test
    public void halfSearch(){
        int arr[] = {3,4,7,9,6,2,-1,45,89,55};
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
        int half = half(9,arr,0,arr.length);
        System.out.println(half);
    }
    
    public int  half(int key,int [] arr,int low,int high){
        if(low>high){
            return -1;
        }
        int mid = low + (high-low)/2;
        //return arr;
        if(arr[mid]>key){
            return half(key,arr,low,mid);
        }else if(arr[mid]<key){
            return half(key, arr, mid+1, high);
        }else{
            return mid;
        }
    }
@Test
    public void half(){
        int arr[] = {3,4,7,9,6,2,-1,45,89,55};
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
        int half = half1(9,arr,arr.length);
        System.out.println(half);
    }
    
    public int  half1(int key,int [] arr,int n){
        int high = n;
        int low = 1;
        int mid;
        while(high>=low){
            mid = (low+high)/2;
            //mid =low + (high-low)*(key-arr[low])/(arr[high]-arr[low]);    书上说这是修改mid 就是插值;插值适合分布比较均匀,表比较长的
            if(key<arr[mid]){
                high = mid-1;
            }else if(key>arr[mid]){
                low = mid+1;
            }else{
                return mid;
            }
        }
        return -1;//没有找到
        
    }

3.2 斐波那契查找

https://www.nowcoder.com/discuss/3345

PS:他的性能是优于其他的。  这三种有序表的查找本质就是分割点的不同。

--------------------------------------------------------------------

4.索引查找

PS:在现实生活中,数据增长非常快。一般采用添加 索引 来处理

1.索引按结构来分,分为   线索、树形索引、多级索引。;

2.线性索引:就是把所有的索引项组织为线性结构。又称为线性表。 重点讲 稠密索引、分块索引、倒排索引

 2.1稠密索引:就是一条记录对应一条索引项。   那么查找的时候就可以用到二分查找.....;但是一条记录对应一个id,有点太多了,内存可能吃不消。

2.2 分块索引:

要求: 块内无序,块间有序

查找过程:先找块,再找索引

3.3倒排索引

*******************************************动态表查询*******************************************

二叉排序树(左小右大)     (BST) binary sort tree

PS:之前那种都是静态的,如果数据量很大的时候,查找会变得很慢。高效的实现查找算法。在

查找时插入和删除的查找表称为动态查找表

 

package search;
/**
 * 难度是在删除这个节点,删除节点还有保存好二叉排序树(binary sort tree)树的结构
 * 
 */
import java.util.Stack;

public class BinarySortTree {
    private Node root = null;  //根节点
     /**中序非递归遍历二叉树 
     * 获得有序序列 
     * */  
    public void nrInOrderTraverse(){  
        Stack<Node> stack = new Stack<Node>();  
        Node node = root;  
        while(node != null || !stack.isEmpty()){  
            while(node != null){  
                stack.push(node);  
                node = node.getLeft();  
            }  
            node = stack.pop();  
            System.out.print(node.getValue()+"  ");  
            node = node.getRight();  
        }  
    }  
     /** 
     * 删除二叉排序树中的结点 
     * 分为三种情况:(删除结点为*p ,其父结点为*f) 
     * (1)要删除的*p结点是叶子结点,只需要修改它的双亲结点的指针为空 
     * (2)若*p只有左子树或者只有右子树,直接让左子树/右子树代替*p 
     * (3)若*p既有左子树,又有右子树 
     *      用p左子树中最大的那个值(即最右端S)代替P,删除s,重接其左子树 
     * */  
    public void deleteBST(int key){  
        deleteBST(root, key);  
    }  
    private boolean deleteBST(Node node, int key) {  
        if(node == null) return false;  
        else{  
            if(key == node.getValue()){  
                return delete(node);  
            }  
            else if(key < node.getValue()){  
                return deleteBST(node.getLeft(), key);  
            }  
            else{  
                return deleteBST(node.getRight(), key);  
            }  
        }  
    }  
    /**
     * 这里是关键
     * @param node
     * @return
     */
    private boolean delete(Node node) {  
        Node temp = null;  
        /**右子树空,只需要重接它的左子树 
         * 如果是叶子结点,在这里也把叶子结点删除了 
         * */  
        if(node.getRight() == null){  
            temp = node;  
            node = node.getLeft();  
        }  
        /**左子树空, 重接它的右子树*/  
        else if(node.getLeft() == null){  
            temp = node;  
            node = node.getRight();  
        }  
        /**左右子树均不为空*/  
        else{  
            temp = node;  
            Node s = node;  
            /**转向左子树,然后向右走到“尽头”*/  
            s = s.getLeft();  
            while(s.getRight() != null){  
                temp = s;  
                s = s.getRight();  
            }  
            node.setValue(s.getValue());  //找节点来保留,下面是重新设置数的结构
            if(temp != node){  
                temp.setRight(s.getLeft());  
            }  
            else{  
                temp.setLeft(s.getLeft());  
            }  
        }  
        return true;  
    }  
    
    public static void main(String[] args) {
        BinarySortTree bst = new BinarySortTree();  
        /**构建的二叉树没有相同元素*/  
        int[] num = {4,7,2,1,10,6,9,3,8,11,2, 0, -2};  
        for(int i = 0; i < num.length; i++){  
            bst.insertBST(num[i]);  
        }  
        bst.nrInOrderTraverse();  
        System.out.println(bst.searchBST(10));  
        System.out.println(bst.searchBST1(-2));  //我自己写的也是对的
        bst.deleteBST(2);  
        bst.nrInOrderTraverse();  
    }
    /**查找二叉排序树中是否有key值*/  
    public boolean searchBST(int key){  
        Node current = root;  
        while(current != null){  
            if(key == current.getValue())  
                return true;  
            else if(key < current.getValue())  
                current = current.getLeft();  
            else  
                current = current.getRight();  
        }  
        return false;  
    }  
    
    public boolean searchBST1(int key){
        return searchBST1(key,root);
    }
    /**查找二叉排序树中是否有key值
     * 递归使用
     * */  
    public boolean searchBST1(int key,Node cur){
        //cur = root;
        if(cur ==null){
            return false;
        }else if(cur.getValue()==key){
            return true;
        }else if(key>cur.getValue()){
            return searchBST1(key, cur.getRight());
        }else if(key<cur.getValue()){
            return searchBST1(key, cur.getLeft());
        }
        return false;  
    }
    /**
     * 向BST插入节点,左小右大
     * @param i
     */
    private void insertBST(int key) {
        Node p = root;
        Node prev =null;
        /**一直查找下去,直到到达满足条件的结点位置*/  
        while(p!=null){
            prev = p;
            if(key>p.getValue()){
                p = p.getRight();
            }else if(key<p.getValue()){
                p=p.getLeft();
            }else{
                return ;
            }
        }
         /**prve是要安放结点的父节点,根据结点值得大小,放在相应的位置*/  
        if(root == null){  
            root = new Node(key);  
        }
        else if(key < prev.getValue()) {
            prev.setLeft(new Node(key));  
        }
        else{
            prev.setRight(new Node(key));  
        }
        
    }

}
/**
 * 二叉链表的数据结构
 * @author bee
 *
 */
class Node{
    private int value;
    private Node left;
    private Node right;
    public Node(int key) {
        this.value = key;
    }
    public int getValue() {
        return value;
    }
    public void setValue(int value) {
        this.value = value;
    }
    public Node getLeft() {
        return left;
    }
    public void setLeft(Node left) {
        this.left = left;
    }
    public Node getRight() {
        return right;
    }
    public void setRight(Node right) {
        this.right = right;
    }
    
}

 ***********AVL(平衡二叉树)*****

PS:他是二叉排序树的一种特例。 特别的地方就是  每一个节点的左子树和右子树的高度差至多为1.  (-1,0,1)平衡因子

     高度差大于等于1的节点为根的子树,称为最小不平衡子树。

    二叉平衡树,创建原理,插入一个节点,看他是否保持平衡。思想就是要不不平衡消灭在最早的时刻。

http://blog.csdn.net/liyong199012/article/details/29219261

*************************多路查找树(B)*****

PS:之前学习的树,都是一个节点只能存储一个元素。多路查找树,就是一个节点孩子的个数可以多余2个。且每一个节点处可以存储多个元素。

孩子数的多少是非常关键的,我们讲解4种形式。 2-3树,2-3-4树。B+和B-树。

PS: 2-3树是B树的一种特例

--红黑树      R-B树                  R-B Tree,全称是Red-Black Tree,又称为“红黑树”,它一种特殊的二叉查找树。红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black)。

http://www.cnblogs.com/skywang12345/p/3245399.html#a1

 ********************************************散列表

PS:之前找一个值需要对比很多,才能找到存储的位置。散列技术就是根据key直接找到存储位置。

PS:HashTable其实是一个内存

 

冲突:  Java是通过hashcode和equals来解决的

 

原文地址:https://www.cnblogs.com/bee-home/p/7530781.html