必须掌握的基本算法

这些代码都有手写的可能性

1. 二分查找

/**
 * @program: 必背算法
 * @description: 二分查找的实现
 * @author: huang xin
 * @create: 2018-11-26 20:57
 */

/**
 * 应用场景:在有序数组中查找某几个数字在数组中的位置
 *
 * 思路:利用数组的有序性,不需要逐个查找。只需要每次与数组中间元素比较
 *  
 * 时间复杂度:O(logn)
 * */
public class BinarySearch {

    /**方法都声明为,类方法(public static)*/

    /**
     * @param  arr 有序数组
     * @param  val  查找元素
     * @return  int  返回元素下标
     * */
    public static int binarySearch(int[] arr, int val){
        int left = 0;
        int right = arr.length-1;
        int mid;
        while (left <= right){
            mid = (right - left)/2 + left;
            if (val == arr[mid]){
                return mid;
            }else if (val > arr[mid]){
                left = mid +1;
            }else {
                right = mid - 1;
            }
        }
        return -1; //数组中没有该值,返回-1
    }

    /**mian用来测试上面的方法正确性*/
    public static void main(String[] args) {

        int[] arr = {2,5,6,7,8,11,14};
        System.out.println(binarySearch(arr,11));
    }
}

2. 冒泡排序

/**
 * @program: 必背算法
 * @description: 冒泡排序
 * @author: huang xin
 * @create: 2018-11-26 21:39
 */

/**
 * 应用场景:给无序的数组排序
 *
 * 思路:依次比较相邻两个数,把大数安排在后面。当数组中只有一个数未排序时,数组就有序了
 *        利用双重for循环,外层控制比较范围,内层控制比较元素
 *
 * */
public class BubbleSort {

    /**
     * @param  arr 未排序数组
     * @return  int[] 已经排好序数组
     * */
    public static int[] bubbleSort(int[] arr){

        for (int length = arr.length -1 ; length > 0 ;length--){ //此处注意java.lang.ArrayIndexOutOfBoundsException

            for (int index = 0; index < length ;index ++){

                if (arr[index] > arr[index+1]){ //比较相邻两个数
                    int temp = arr[index];
                    arr[index] = arr[index+1];
                    arr[index+1] = temp;
                }
            }
        }
        return arr;
    }
    public static void main(String[] args) {

        int[] arr = {24,65,2,-7,8,24,654,};
        bubbleSort(arr);
        for (int a : arr){ //增强for遍历
            System.out.print(a + ",");
        }
    }
}

注意改进的冒泡法

 /**
     * 对于基本有序的数组可以优化算法,例如:7 ,1,2,3,4,5
     * 采用设置标志位,判断没有发生相邻两个元素交换就跳出循环
     * */
    public static int[] bubbleSort2(int[] arr){

        boolean flag = true;
        int length = arr.length -1;
        while (flag){
            flag = false; //本次内循环若无元素交换,则判定后面元素是有序的。不再进行排序
            for (int j = 0 ;j < length; j ++){  //在length等于某个值时,遍历一次数组发现都是后面的数大。标志位为false退出外层循环。
                if (arr[j] > arr[j+1]){ //一旦发生一次后面的数小,标志位就改变
                  int temp = arr[j+1];
                  arr[j+1] = arr[j];
                  arr[j] = temp;
                  flag = true;
                }
            }
            length --;
        }
        return arr;
    }
/**
     * 还有一种情况:数据量很大,但只有前200是无序的,后面的有序且比前面的大
     *
     * 思路:找到前面无序和后面有序的分界点,即第一次全数组遍历发现后面前面数不大于后面数时。下次就只遍历到这个地方
     *      i是活动的表示前几个数还未排序
     * */
    public static int[] sort3(int[] arr){
        int flag = arr.length -1;
        while (flag > 0){
            int k = flag;  //k来记录遍历的尾边界
            flag = 0;

            for (int j = 0 ; j < k ; j ++){ //k在变化,内循环不用遍历所用,只遍历前面无序部分

                if (arr[j] > arr[j+1]){ //没发生交换,代表已经有序了,flag在循环中没有赋值,外层默认为0 退出while
                    int temp = arr[j+1];
                    arr[j+1] = arr[j];
                    arr[j] = temp;
                    flag = j;  //记录每次内循环的尾边界
                }
            }
        }
        return arr;
    }

3、快排

这种排序思想,找了很多种代码实现方式。发现有一种可以理解

核心:partition加递归,使partition点的左边小,右边大。然后找中间区域新的partition,递归下去直到左边界大于右边界。

/**
 * 关键是:如何写partition,后面直接递归
 * */
public class QuickSort {

    /**
     * 返回partition的点,是之前元素小,之后元素大
     */
    /**
     * @param  arr 待排序数组
     * @param  l, 区间左边界
     * @param  r ,区间右边界
     * @return  标定点该在数组的位置
     * */
    public static int partition(int[] arr, int l, int r) {
        //目的:遍历数组,把arr[l]安排到合适位置
        int partition = arr[l];
        int j = l;          //维护区间 arr[l+1,j] < v ,arr[j+1 ,i) >v

        for (int i = l + 1; i <= r; i++) { //i表示正在遍历的数,从第二个开始,
                                            // 如果小于partition,与前面区间的末尾(j+1)交换
                                            //若大于partition,当前遍历元素不变,遍历指针后移(i++)
            if (arr[i] < partition) {
                j++;
                //交换arr[i] 与arr[j+1]
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
        //结束循环后,将partition移到中间,即交换l与j的位置
        int temp = arr[l];
        arr[l] = arr[j];
        arr[j] = temp;

        return j; //返回
    }
    /**快排*/
    public static void sort(int[] arr, int l, int r) {

        if (l >= r) {           //递归结束条件
            return;
        }
        int p = partition(arr, l, r); //找标定点,对左右区间再进行排序
        sort(arr, l, p - 1);
        sort(arr, p + 1, r);
    }
    public static void main(String[] args) {
        int[] arr2 = {789, 1, 654, 6, 8, 24, 3};
        sort(arr2, 0, 6);
        for (int a : arr2)
            System.out.print(a + ",");
    }
}

还要加树的遍历和链表的操作

4、二叉树的遍历

public class BinaryTree {

    /**声明一棵树,它有一个值域,两个指针域*/
    class Node{
        public int data;
        public Node left; //左子树
        public Node right; //右子树
        public Node(int date ,Node right ,Node left){
            this.data =date;
            this.right = right;
            this.left = left;
        }
    }
    /**采用递归遍历,前序、中序、后序*/
    /**
     * @param root 给定一个二叉树根节点
     * */
    public static void preOrder(Node root){
        if (root != null){
            System.out.print(root.data + ",");
            preOrder(root.left);
            preOrder(root.right);
        }
    }
    /**
     * @param root 传入数的根节点
     * */
    public static void middleOrder(Node root){
        if (root != null){
            middleOrder(root.left);
            System.out.print(root.data + ",");
            middleOrder(root.right);
        }
    }

    public static void afterOrder(Node root){
        if (root != null){
            afterOrder(root.left);
            afterOrder(root.right);
            System.out.print(root.data + ",");
        }
    }

    /**采用非递归方式遍历*/

    /** 层序遍历:用队列实现
     * 特点:先进的节点先出去,本质依次存入依次出队
     * */
    public static void levelOrder(Node root){

        if (root == null)
            return;

        LinkedList<Node> linkedList = new LinkedList<>(); //创建队列
        linkedList.offer(root);  //头结点入队
        while (!linkedList.isEmpty()){
            Node node = linkedList.poll(); //出队,拿到对列的元素
            System.out.println(node.data); //打印数据
            //左右节点不为空,就要依次入队
            if (node.left != null){
                linkedList.offer(node.left);
            }
            if (node.right != null){
                linkedList.offer(node.right);
            }
        }
    }

    /**非递归前序:用Stack模拟栈
     * 注意:为了保证先打印左子树,需要右子树先入栈
     * */
    public static void noPreOrder(Node root){

        Stack<Node> stack = new Stack<>(); //创建了一个栈

        stack.push(root); //将树的头结点放入栈中

        Node p = null; //定义一个节点的引用来指向出栈的节点
        while (!stack.isEmpty()){ //栈不为空就可以出栈
            p = stack.pop();
            if (p != null){
                System.out.println(p.data);
                stack.push(p.right);
                stack.push(p.left);
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值