递归,汉诺塔,冒泡排序,选择排序,插入排序,快速排序

package com.itheima;

/**
* 常用的各种算法
*
* @author Administrator
*
*/
public class SuanFa {

/**
 * <<递归算法>>
 * 
 * @param number
 * @return 求出1到number的数字之和
 */
public static int sum(int number) {
    if (number < 1) {
        throw new RuntimeException("number must > 0");
    } else if (number == 1) {
        return 1;
    } else {
        return number + sum(number - 1);
    }
}

// 移动的次数
private static int counts = 0;

/**
 * 递归的经典应用:汉诺塔问题 移动的次数
 * 
 * @param panNum
 *            盘的数量
 * @param a
 *            abc三个塔
 * @param b
 * @param c
 */
public static void moveNumber(int panNum, char a, char b, char c) {
    // 每一次移动数量都要加1
    counts++;
    if (panNum != 1) {
        moveNumber(panNum - 1, a, c, b);
        moveNumber(panNum - 1, b, a, c);

    }

}

/**
 * 移动的顺序或者步骤
 * 
 * @param panNum
 * @param a
 * @param b
 * @param c
 */
public static void move(int panNum, char a, char b, char c) {
    if (panNum == 1) {// 如果只有一个盘就直接从a柱移动到c柱
        System.out.println("盘:" + panNum + "从" + a + "柱移动到" + c + "柱");
    } else {// 如果盘的个数大于1的话
        // 递归
        move(panNum - 1, a, c, b);// 先把n-1 个盘从a盘移动到b盘
        // 此时a盘的数量剩余1个走上一步路线
        System.out.println("盘:" + panNum + "从" + a + "柱移动到" + c + "柱");
        move(panNum - 1, b, a, c);// 最后把b柱上的n-1个盘从b柱直接移动到c柱
    }
}

/**
 * 初始化数据
 * 
 * @param datas
 */
public static void initData(int datas[]) {
    for (int i = 0; i < datas.length; i++) {
        // 所有的数字都是随机从1到100的整数
        datas[i] = (int) (Math.random() * 100) + 1;
    }
}

/**
 * 打印数据
 * 
 * @param datas
 * @return
 */
public static void printData(int datas[]) {
    for (int i = 0; i < datas.length; i++) {
        System.out.println(datas[i] + ",");
    }
    // 换行
    System.out.println();

}

/**
 * <<冒泡排序>>
 * 冒泡排序是一种简单的交换类排序。其基本思路是,从头开始扫描待排序的元素,在扫描过程中依次对相邻元素进行比较,将关键字值大的元素后移。
 * 每经过一趟排序后,关键字值最大的元素将移到末尾,此时记下该元素的位置,下一趟排序只需要比较到此位置为止,直到所有元素都已有序排列。
 * 
 * 一般地,对n个元素进行冒泡排序,总共需要进行n-1趟。第1趟需要比较n-1次,第2趟需要比较n-2次,......第i趟需要比较n-i次。
 * 
 * @param datas
 */
public static void bubbleSort(int datas[]) {
    int temp = 0;
    for (int i = 0; i < datas.length - 1; i++) {// 比较的趟数
        for (int j = 0; j < datas.length - i - 1; j++) {// 每趟比较的次数
            if (datas[j] > datas[j + 1]) {// 从小到大排序
                temp = datas[j];
                datas[j] = datas[j + 1];
                datas[j + 1] = temp;
            }
        }
    }
}

/**
 * <<选择排序>>
 * 
 * @param datas
 */
public static void selectSort(int datas[]) {
    for (int i = 0; i < datas.length - 1; i++) {// 和冒泡的比较次数相同
        int minIndex = i;// 记录最小元素的下标
        for (int j = i + 1; j < datas.length; j++) {
            if (datas[minIndex] > datas[j]) {
                // 重新复制下标
                minIndex = j;

            }

        }
        int temp = datas[i];
        datas[i] = datas[minIndex];
        datas[minIndex] = temp;
    }
}

/**
 * <<插入排序>>也就是从第二个位置开始,和他前面的数字比较,如果该数字比前面的数字大,就交换位置
 * 
 * @param datas
 */
public static void insertSort(int datas[]) {
    int i = 0;// 插入的次数
    int j = 0;// 第二个数据开始插入的下标
    for (i = 1; i < datas.length; i++) {// 插入的次数(从第二个开始)
        // 定义一个存放该数据的临时变量
        int temp = datas[i];
        for (j = i - 1; j >= 0; j--) {
            // 和他前面的数依次比较
            if (datas[j] > temp) {
                datas[j + 1] = datas[j];
            } else {
                break;
            }
        }
        // 判断就是跳出循环j == -1或者就是第一个<= temp数据的位置
        datas[j + 1] = temp;
    }
}

/**
 * <<快速排序>>思想:以最后一个位置上的数据作为参照物画一条横线,一眼可以看出谁比参照物大或者小,在开始位置和结束位置分别定义两个指针left和right,
 *               左指针向右移动找到第一个比参照物大的数据,右指针往左移动,找到第一个比参照物小的数据,如果没有交叉;交换左右指针位置上的数据,继续按照此方法寻找,
 *               如果出现交叉,就交换左指针对应的数据和参照物,这样左指针的位置也就是参照物就把数据分成了两半,左边的都比自己小,右边的都比自己大,左右两半数据采用同样的方式
 *               继续寻找,这也就是递归,直到把所有的数据都按照从小到大排序。
 * @param datas  数组
 * @param statrt 开始数据
 * @param end    结束数据
 */
public static void quickSort(int datas[], int start, int end){
    //如果就一个数
    if ( start >= end) {
        return;
    } else {
        //如果多于一个数
        int middle = findMiddle(datas, start, end);
        //递归
        quickSort(datas, start, middle - 1);
        quickSort(datas, middle + 1, end);
    }


}
/**
 * 寻找中间数(具体的算法精髓在这个方法中)上面只是一个壳子,调用了该方法
 * @param datas
 * @param start
 * @param end
 */
private static int findMiddle(int datas[], int start, int end){
    //把最后一个数作为参照物
    int temp = datas[end];
    //分别定义左右指针
    int left = start;
    int right = end - 1;
    //循环寻找
    while (true) {
        //1.左指针往右寻找,找到第一个比参照物大的数据
        while (left < end && datas[left] <= temp) {
            left ++ ;
        }
        //2.右指针往左移动,找到第一个比参照物小的数据
        while (right >= start && datas[right] >= temp) {
            right -- ;

        }
        //如果参照物是最大值结束
        if (left == end) {
            break;
        }
        //3.比较是否出现交叉(left和right)
        if (left < right) {
            //4.如果没有出现交叉,交换左右指针位置对应的数据
            int d = datas[left];
            datas[left] = datas[right];
            datas[right] = d;

        } else {
            //5.如果出现交叉,交换左指针位置的数据和参照物,结束
            int d = datas[left];
            datas[left] = datas[end];
            datas[end] = d;
            break;
        }

    }
    return left;

}
public static void main(String[] args) {
    // 1.测试递归算法
    System.out.println(sum(100));
    // 2.测试汉诺塔的移动次数
    moveNumber(3, 'a', 'b', 'c');
    System.out.println(counts);
    // 3.测试汉诺塔的移动步骤
    move(3, 'a', 'b', 'c');
    // 4.初始化和打印数据
    int[] datas = new int[10];
    initData(datas);// 初始化1000个1~100之间的数字
    printData(datas);// 吧数字打印出来
    /*
     * // 5.测试冒泡排序 System.out.println("***********冒泡排序****************");
     * bubbleSort(datas); printData(datas);// 把数字打印出来
     */
    // 6.测试选择排序
    /*
     * System.out.println("***********选择排序****************");
     * selectSort(datas); printData(datas);
     */
    // 7.测试插入排序
    /*System.out.println("***********插入排序****************");
    insertSort(datas);
    printData(datas);*/
    //8.测试快速排序
    System.out.println("***********快速排序****************");
    //开始时间
    System.out.println(System.currentTimeMillis());

    quickSort(datas, 0, datas.length - 1);

    //结束时间
    System.out.println(System.currentTimeMillis());
    printData(datas);

}

}

你可能感兴趣的:(算法,冒泡排序,递归,插入排序,快速排序)