数据结构与算法无用随笔

1、基于链表实现的LRU(Least Recently Used 最近最少使用失效原则)缓存

  1 public class Mycache {
  2     private int count = 0;
  3     private Node head = null;
  4     
  5     class Node {
  6         private String key;
  7         private int value;
  8         private Node next = null;
  9         
 10         public Node(String key, int value, Node next) {
 11             this.key = key;
 12             this.value = value;
 13             this.next = next;
 14         }
 15         public String getKey() {
 16             return key;
 17         }
 18         public void setKey(String key) {
 19             this.key = key;
 20         }
 21         public int getValue() {
 22             return value;
 23         }
 24         public void setValue(int value) {
 25             this.value = value;
 26         }
 27         public Node getNext() {
 28             return next;
 29         }
 30         public void setNext(Node next) {
 31             this.next = next;
 32         }
 33     }
 34     
 35     public void save(String key, int value) {
 36         if(head != null) {
 37             Node item = head;
 38             do {
 39                 if(item.getKey().equals(key)) {
 40                     item.setValue(value);
 41                     return;
 42                 }
 43                 item = item.next;
 44             }while(item != null);
 45             
 46             if(count < 5) {
 47                 item = head;
 48                 head = new Node(key, value, null);
 49                 head.next = item;
 50                 count++;
 51             }else {
 52                 System.out.println("基于LRU缓存策略移除队尾元素");
 53                 
 54                 Node itemToRemove = head;
 55                 while(itemToRemove.next != null) {
 56                     itemToRemove = itemToRemove.next;
 57                 }
 58                 
 59                 item = head;
 60                 while(item.next != itemToRemove) {
 61                     item = item.next;
 62                 }
 63                 item.next = null;
 64                 
 65                 item = head;
 66                 head = new Node(key, value, null);
 67                 head.next = item;
 68             }
 69         }else {
 70             head = new Node(key, value, null);
 71             count++;
 72         }
 73     }
 74     public int get(String key) {
 75         int result = 0;
 76         Node itemToRemove = head;
 77         do {
 78             if(itemToRemove.getKey().equals(key)) {
 79                 result = itemToRemove.getValue();
 80                 
 81                 Node item = head;
 82                 while(item.next != itemToRemove) {
 83                     item = item.next;
 84                 }
 85                 item.next = itemToRemove.next;
 86                 
 87                 itemToRemove.next = head;
 88                 head = itemToRemove;
 89                 
 90                 return result;
 91             }
 92             itemToRemove = itemToRemove.next;
 93         }while(itemToRemove != null);
 94         
 95         throw new RuntimeException("缓存中没有对应的数据");
 96     }
 97     
 98     public void iterate() {
 99         Node item = head;
100         while(item != null) {
101             System.out.println("【key=" + item.getKey() + ",value=" + item.getValue() + "");
102             item = item.next;
103         }
104     }
105     public static void main(String[] args) {
106         Mycache cache = new Mycache();
107         cache.save("a", 1);
108         cache.iterate();
109         System.out.println("----------------");
110         cache.save("b", 2);
111         cache.iterate();
112         System.out.println("----------------");
113         cache.save("c", 3);
114         cache.iterate();
115         System.out.println("----------------");
116         cache.save("d", 4);
117         cache.iterate();
118         System.out.println("----------------");
119         cache.save("e", 5);
120         cache.iterate();
121         System.out.println("----------------");
122         cache.save("f", 6);
123         cache.iterate();
124         System.out.println("----------------");
125         int result = cache.get("b");
126         System.out.println(result);
127         cache.iterate();
128     }
129 }

 2、基于数组实现的顺序栈

//基于数组实现的顺序栈
public class ArrayStack {
    private int[] items;//数组
    private int n;//栈的大小
    private int count;//栈中元素个数
    
    public ArrayStack(int n) {
        items = new int[n];
        this.n = n;
        this.count = 0;
    }
    
    //入栈操作
    public boolean push(int value) {
        //数组空间不足,直接返回false,入栈失败
        if(count >= n) {
            return false;
        }
        //将item放到下标为count的位置,并且count自增1
        items[count++] = value;
        return true;
    }
    //出栈操作
    public int pop() {
        //栈为空,则直接返回null
        if(count <= 0) {
            return -9999;
        }
        //返回下标为count-1的数组元素,并且栈中元素个数count自减1
        return items[--count];
    }
    
    public static void main(String[] args) {
        ArrayStack stack = new ArrayStack(3);
        stack.push(11);
        stack.push(22);
        stack.push(33);
        stack.push(44);
        
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        stack.push(555);
        System.out.println(stack.pop());
        System.out.println(stack.pop());
    }
}

3、基于链表实现的链式栈

//基于链表实现的链式栈
public class LinkedListStack {
    //哨兵机制,带头节点
    private Node head = new Node(null);
    
    //入栈操作
    public void push(String value) {
        if(value == null) {
            return;
        }
        Node newNode = new Node(value);
        newNode.next = head.next;
        head.next = newNode;
    }
    //出栈操作
    public String pop() {
        Node result = head.next;
        if(result == null) {
            return null;
        }
        head.next = result.next;
        return result.value;
    }
    
    class Node{
        private String value;
        private Node next = null;
        
        public Node(String value) {
            this.value = value;
        }
    }
    
    public static void main(String[] args) {
        LinkedListStack stack = new LinkedListStack();
        stack.push("aa");
        stack.push("bb");
        stack.push("cc");
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        stack.push("1111");
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.pop());
    }
}

4、使用两个栈实现的加减乘除四则混合运算的编译器

public class Expression {
    //操作数栈
    private ArrayStack operandStack = new ArrayStack(20);
    //运算符栈
    private LinkedListStack operatorStack = new LinkedListStack();
    
    public int process(String expression) {
        int result = 0;
        String exp = expression;
        int firstOperatorIndex = 9999;
        do {
            firstOperatorIndex = getFirstOperatorIndex(exp);
            if(firstOperatorIndex == 9999) {
                break;
            }
            //操作数入栈
            operandStack.push(Integer.parseInt(exp.substring(0, firstOperatorIndex)));
            
            //运算符入栈
            String topOperator = operatorStack.pop();
            String currOperator = exp.substring(firstOperatorIndex, firstOperatorIndex+1);
            boolean priorityCompare = true;
            while(!(priorityCompare = priorityCompare(currOperator, topOperator))) {
                int operand1 = operandStack.pop();
                int operand2 = operandStack.pop();
                int tmpResult = cal(operand1, operand2, topOperator);
                operandStack.push(tmpResult);
                topOperator = operatorStack.pop();
            }
            operatorStack.push(topOperator);
            operatorStack.push(currOperator);
            
            exp = exp.substring(firstOperatorIndex + 1);
        }while(!exp.isEmpty());
        operandStack.push(Integer.parseInt(exp));    
        
        String operand = null;
        while((operand = operatorStack.pop()) != null) {
            int operand1 = operandStack.pop();
            int operand2 = operandStack.pop();
            int tmpResult = cal(operand1, operand2, operand);
            operandStack.push(tmpResult);
        }
        
        return operandStack.pop();
    }
    
    private int getFirstOperatorIndex(String expression) {
        int addIndex = expression.indexOf("+");
        int minusIndex = expression.indexOf("-");
        int mulIndex = expression.indexOf("*");
        int divIndex = expression.indexOf("/");
        int firstOperatorIndex = 9999;
        if(addIndex > 0) {
            firstOperatorIndex = Math.min(firstOperatorIndex, addIndex);
        }
        if(minusIndex > 0) {
            firstOperatorIndex = Math.min(firstOperatorIndex, minusIndex);
        }
        if(mulIndex > 0) {
            firstOperatorIndex = Math.min(firstOperatorIndex, mulIndex);
        }
        if(divIndex > 0) {
            firstOperatorIndex = Math.min(firstOperatorIndex, divIndex);
        }
        return firstOperatorIndex;
    }
    //如果source优先级比target高,则返回true,否则返回false
    private boolean priorityCompare(String source, String target) {
        if(target == null) {
            return true;
        }
        if((source.equals("*") || source.equals("/")) && (target.equals("+") || target.equals("-"))) {
            return true;
        }
        return false;
    }
    //运算
    private int cal(int operand1, int operand2, String operator) {
        int result = 0;
        if(operator.equals("+")) {
            result = operand2 + operand1;
        }else if(operator.equals("-")) {
            result = operand2 - operand1;
        }else if(operator.equals("*")) {
            result = operand2 * operand1;
        }else if(operator.equals("/")) {
            result = operand2 / operand1;
        }
        
        return result;
    }
    
    public static void main(String[] args) {
        Expression expression = new Expression();
        System.out.println(expression.process("2+5*4-8/2-1+3*2"));
    }
}

 5、二分查找

/*
 * 问题:假设我们有1000万个整数数据,每个数据占8个字节,如何设计数据结构和算法,快速判断某个整数是否出现在这1000万数据中?
 * 分析:1000万个整数数据,每个数据占8个字节,存储在数组中,内存占用差不多是80MB,采用二分查找时间复杂度为O(logn),并且
 *     二分查找除了数据本身之外,不需要额外存储其他信息,符合内存的限制。我们说,二分查找是最省内存空间的快速查找算法。
 */

/**
 * 二分查找算法:针对的是一个有序的数据集合,时间复杂度为O(logn)
 * @author Administrator
 *
 * 二分查找应用场景的局限性
 *   1、二分查找只能用在数据是通过顺序表来存储的数据结构上,简单点说就是二分查找只适合用于数组,因为二分查找算法
 *     需要按照下标随机访问元素
 *   2、二分查找针对的是有序数据,只适合用在插入、删除操作不频繁,一次排序多次查找的场景中,不适用于动态变化的数据集合
 *   3、数据量太大不适合二分查找,原因是二分查找的底层依赖数组这种数据结构,而数组为了支持随机访问的特性,要求使用
 *     连续的内存空间,太大量的数据不适合用连续的内存空间存储
 */
public class BinarySearch {
    
    /**
     * 最简单情况(有序数组中不存在重复元素)  用循环实现
     * @param a      给定的有序数组
     * @param value  待查找的目标值
     * @return       查找结果的下标
     */
    public int simpleSearchBaseLoop(int[] a, int value) {
        //当前查找的区间范围
        int low = 0, high = a.length - 1;
        //中间位置
        int mid = 0;
        //终止条件(1、区间缩小为0(low>high)  2、 找到目标值)
        while(low <= high) {
            //计算当前查找区间范围的中间位置
            mid = (low + high)/2;
            //当前查找区间范围的中间位置的值与目标值进行比较
            if(a[mid] == value) {
                return mid;
            }else if(a[mid] < value) {
                low = mid + 1;
            }else {
                high = mid - 1;
            }
        }
        return -1;
    }
    /**
     * 需要注意的3个地方:
     *   1、循环执行条件是 low <= high,而不是low < high
     *   2、mid的取值  mid=(low+high)/2 这种写法实际上是有问题的,因为如果low和high比较大的话,两者之和就有可能会溢出。
     *     改进的方法是将 mid 的计算方式写成 mid=low+(high-low)/2。更进一步,如果要将性能优化到极致的话,我们可以将这里
     *     的除以2操作转化成位运算 mid=low+((high-low)>>1),因为相比除法来说,计算机处理位运算要快得多
     *   3、low和high的更新是 low=mid+1,high=mid-1,如果直接写成low=mid,high=mid 就有可能会发生死循环,比如
     *     当high=3,low=3,并且a[3]不等于value时,就会导致一直循环不退出
     */
    
    /**
     * 最简单情况(有序数组中不存在重复元素)  用递归实现
     * @param a     给定的有序数组
     * @param low   当前查找范围的最小值
     * @param high  当前查找范围的最大值
     * @param value 待查找的目标值
     * @return      查找结果的下标
     */
    public int simpleSearchBaseRecursion(int[] a, int low, int high, int value) {
        //判断当前查找范围是否已经缩小为0
        if(low > high) {
            return -1;
        }
        
        int mid = low + ((high-low)>>1);
        if(a[mid] == value) {
            //找到目标值直接返回
            return mid;
        }else if(a[mid] < value) {
            //未找到目标值,缩小范围递归查找
            return simpleSearchBaseRecursion(a, mid+1, high, value);
        }else {
            //未找到目标值,缩小范围递归查找
            return simpleSearchBaseRecursion(a, low, mid-1, value);
        }
    }
    
    /**
     * 二分查找变种1:查找第一个值等于给定值的元素
     * @param a      给定的有序数组
     * @param value  待查找的目标值
     * @return       查找结果的下标
     */
    public int binarySearchVarietas1(int[] a, int value) {
        /*************简洁写法*********************
        int n = a.length;
        int low = 0, high = n - 1;
        int mid = 0;
        
        while(low <= high) {
            mid = low + ((high - low)>>1);
            if(a[mid] < value) {
                low = mid + 1;
            }else {
                high = mid - 1;
            }
        }
        
        //如果low<n,则说明value在[a[0], a[n-1]]范围内,此时只需要判断a[low]是否等于value即可
        if(low < n && a[low] == value) {
            return low;
        }else {
            return -1;
        }
        ************************************/
        int n = a.length;
        int low = 0, high = n - 1;
        int mid = 0;
        
        while(low <= high) {
            mid = low + ((high - low)>>1);
            if(a[mid] < value) {
                low = mid + 1;
            }else if(a[mid] > value) {
                high = mid - 1;
            }else {
                //判断是否是第一个等于value的元素
                if(mid == 0 || a[mid-1] != value) {
                    return mid;
                }
                high = mid - 1;
            }
        }
        
        return -1;
    }
    
    /**
     * 二分查找变种2:查找最后一个值等于给定值的元素
     * @param a      给定的有序数组
     * @param value  待查找的目标值
     * @return       查找结果的下标
     */
    public int binarySearchVarietas2(int[] a, int value) {
        int n = a.length;
        int low = 0, high = n - 1;
        int mid = 0;
        
        while(low <= high) {
            mid = low + ((high - low)>>1);
            if(a[mid] < value) {
                low = mid + 1;
            }else if(a[mid] > value) {
                high = mid - 1;
            }else {
                //判断是否是最后一个等于value的元素
                if(mid == n-1 || a[mid+1] != value) {
                    return mid;
                }
                low = mid + 1;
            }
        }
        
        return -1;
    }
    
    /**
     * 二分查找变种3:查找第一个大于等于给定值的元素
     * @param a      给定的有序数组
     * @param value  待查找的目标值
     * @return       查找结果的下标
     */
    public int binarySearchVarietas3(int[] a, int value) {
        int n = a.length;
        int low = 0, high = n - 1;
        int mid = 0;
        
        while(low <= high) {
            mid = low + ((high - low)>>1);
            if(a[mid] < value) {
                low = mid + 1;
            }else {
                //判断是否是第一个小于等于value的元素
                if(mid == 0 || a[mid-1] < value) {
                    return mid;
                }
                high = mid - 1;
            }
        }
        
        return -1;
    }
    
    /**
     * 二分查找变种4:查找最后一个小于等于给定值的元素
     * @param a      给定的有序数组
     * @param value  待查找的目标值
     * @return       查找结果的下标
     */
    public int binarySearchVarietas4(int[] a, int value) {
        int n = a.length;
        int low = 0, high = n - 1;
        int mid = 0;
        
        while(low <= high) {
            mid = low + ((high - low)>>1);
            if(a[mid] > value) {
                high = mid - 1;
            }else {
                //判断是否是最后一个等于value的元素
                if(mid == n-1 || a[mid+1] > value) {
                    return mid;
                }
                low = mid + 1;
            }
        }
        
        return -1;
    }
}

 

posted @ 2019-04-23 10:06  将王相  阅读(208)  评论(0编辑  收藏  举报