• 查找


    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来解决的

     

  • 相关阅读:
    微信小程序从零开始开发步骤(三)
    微信小程序从零开始开发步骤(三)底部导航栏
    微信小程序从零开始开发步骤(二)
    微信小程序从零开始开发步骤(二)
    微信小程序从零开始开发步骤(一)
    [NOIP2016]组合数问题
    5.20 考试 20 未完
    lca 例题 WK
    rmq RMQ
    BZ
  • 原文地址:https://www.cnblogs.com/bee-home/p/7530781.html
Copyright © 2020-2023  润新知