算法——排序算法

数据结构+算法=程序

结构:实体+关系

数据结构的三个方面:逻辑结构(线性(表,栈,队列,串)树,图,二叉树,线性表),存储结构(顺序方法,链接方法,索引方法,散列方法),运算

索引方法(是顺序存储的延伸)和散列方法(借助顺序存储的按照下标来存储的o1的思想,不仅是存储方法,也是运算方法)使数据的检索更加高效

内存:算法运行速度快

外存:相比内存的读取数据,比内存满二十五万倍

 

一刀切上式:事先补齐法

public class A {

  public static void main(String[] args) {
      //上式:事先补齐
    String s="abc ttt,kmd,uuu xyz";
    String s2="";
    s+=',';//一刀切
    for (int i = 0; i < s.length(); i++) {
        char c=s.charAt(i);
        if(c==' ' || c==','){
            System.out.println(s2);
            s2="";
        }
        else
            s2+=c;
    }
  }
}

冒泡排序:

整体思路就是把最大的数依次往后挪

思路:相邻两个数据进行比较,如果位置不对,进行交换,整个数组中未排序的数都比较了一遍。(这样比较完一次使得最大的数在最后边)

每一趟保证把最大的数挪到当前未排好序的数据的最后。(要比较n-1趟)

每一趟要比较多少次(第一趟:n-1次。后面会随着趟数的增加,比较次数会逐渐减少,每次减少1)

用外层循环控制趟数,用内层循环控制次数。

代码实现:

public class BubbleSort {
    public static void main(String[] args) {
        int[] number = { 18, 32, 26, 11, 9, 13, 24, 35, 24 };
        int n = number.length;
        for (int i = 1; i < n - 1; i++) {// n-1趟
            for (int j = 1; j < n - i; j++) {// 每趟里面比较多少次
                if (number[j - 1] > number[j]) {// 将大的数向后挪
                    int temp = number[j - 1];
                    number[j - 1] = number[j];
                    number[j] = temp;
                }
            }

        }
        // 打印
        for (int i = 0; i < number.length; i++) {
            System.out.print(number[i] + "\t");
        }
    }
}

 

快速排序:在元素数据很大的时候效率十分明显。

思想:先去找一个元素作为标尺,我们通常选第一个元素

将这个标尺的元素设为x。然后把比x大 的放在右边,把比x小的放在左边

代码实现思路:要想进行递归完成快速排序就需要先进行一趟排序,将标尺元素放在数组的中间,得出标尺左边是比标尺小的数据,标尺右边是比标尺大的元素。然后对标尺左边和标尺右边的元素进行递归排序。

原来的数据

取标尺

第一个位置的5原来在倒数第二的位置上,将5和标尺进行

 

两边都有一个指针,左边的向右移动,右边的向左移动。直到左右指针撞到一起就完成了排序。

 

用代码递归的完成排序(一):

package cn.taiji.com.com;

public class MyA {

    static void show(int[] a) {
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i] + "");
            System.out.print(" ");
        }
    }

    static void quickSort(int[] a, int begin, int end) {
        if (end - begin <= 1) {// 不需要排序
            return;
        }
        int x = a[begin];// 用begin元素(第一个元素)作为标尺
        int p1 = begin;// 定义两个指针,一个从开始位置指向
        int p2 = end;// 一个从结束位置指向
        boolean dr = true;// 比较条件

        // 当p1等于p2的时候,排序结束
        // 正向,标尺拿走之后,p1位置的是空位,我们需要从p2位置逐步的向左来比较,发现更小的元素
        L1: while (p1 < p2) {
            if (dr) {
                for (int i = p2; i > p1; i--) {
                    if (a[i] <= x) {
                        a[p1++] = a[i];
                        p2 = i;
                        dr = !dr;// 表示原来向左比较,现在向右,原来如果向右,现在向左比较。
                        continue L1;
                    }
                }
                // 不满足条件的元素怎样处理
                p2 = p1;
            }
            // 向左比较
            else {
                for (int i = p1; i < p2; i++) {
                    if (a[i] >= x) {
                        a[p2--] = a[i];
                        p1 = i;
                        dr = !dr;
                        continue L1;
                    }
                }
                p1 = p2;// 将左指针移动到右指针位置
            }
        }
        // 最后将标尺元素塞入到指针相撞的位置
        a[p1] = x;

        quickSort(a, begin, p1 - 1);
        quickSort(a, p1 + 1, end);
    }

    public static void main(String[] args) {
        int[] a = { 15, 22, 13, 9, 16, 33, 15, 23, 18, 4, 33, 25, 14 };
        show(a);
        quickSort(a, 0, a.length - 1);// 快速排序需要递归来完成,除了传递数据,还需要传递数据的范围
        System.out.println();
        show(a);
    }
}

用代码递归的完成排序(二):

package cn.taiji.com.com;

public class QuickSort {

    public static void quickSort(int[] arr, int start, int end) {
        if (start < end) {
            // 拆分索引位
            int index = getIndex(arr, start, end);
            //向左递归
            quickSort(arr, 0, index - 1);
            //向右递归
            quickSort(arr, index + 1, end);
        }
    }

    /**
     * 分区并返回索引值
     *
     * @param arr
     * @param start
     * @param end
     * @return
     */
    public static int getIndex(int[] arr, int start, int end) {
        int i = start;
        int j = end;
        // 第一个坑位
        int x = arr[i];// x是基准数
        while (i < j) {
            // 先从右向左对比,比小于x的
            while (i < j && arr[j] >= x) {
                j--;
            }
            if (i < j) {
                // 把找到的元素放在第一个坑位
                arr[i] = arr[j];
                i++;
            }

            // 从左边向右对比,大于等于x的数
            while (i < j && arr[i] < x) {
                i++;
            }
            if (i < j) {
                arr[j] = arr[i];
                j--;
            }
        }
        arr[i] = x;
        return i;
    }

    public static void main(String[] args) {
        int[] arr = { 5, 3, 9, 1, 6, 7, 2, 4, 0, 8 };
        quickSort(arr, 0, arr.length - 1);
        for (int i : arr) {
            System.out.print(i+" ");
        }

    }

}

 

那么我们可以思考如果这个给的数据有的顺序已经排好,有的趟不需要交换。那么还要交换就影响效率。

解决办法:

public class BubbleSort {
    public static void main(String[] args) {
        int[] number = { 18, 32, 26, 11, 9, 13, 24, 35, 24 };
        int n = number.length;
        for (int i = 1; i < n - 1; i++) {// n-1趟
            boolean flag=false;
            for (int j = 1; j < n - i; j++) {// 每趟里面比较多少次
                if (number[j - 1] > number[j]) {// 将大的数向后挪
                    int temp = number[j - 1];
                    number[j - 1] = number[j];
                    number[j] = temp;
                    flag=true;
                }
            }
            if(!flag){//说明没有进上面的for循环,没有交换
                break;
            }

        }
        // 打印
        for (int i = 0; i < number.length; i++) {
            System.out.print(number[i] + "\t");
        }
    }

}

由于还是调换次数很多,所以冒泡排序的效率还是很低。

 

选择排序:不稳定的,但是效率高

public class Choose {

    public static void main(String[] args) {
        int[] nums = { 34, 4, 56, 17, 90, 65 };
        int minIndex = 0;// 用于记录每次比较的最小值下标
        // 控制轮数
        for (int i = 0; i < nums.length - 1; i++) {
            minIndex = i;// 每轮假设一个最小值下标
            for (int j = i + 1; j < nums.length; j++) {
                if (nums[minIndex] > nums[j]) {
                    minIndex = j;
                }
            }
            // 判断需要交换的数下标是否为自己
            if (minIndex != i) {
                nums[minIndex] = nums[minIndex] + nums[i];
                nums[i] = nums[minIndex] - nums[i];
                nums[minIndex] = nums[minIndex] - nums[i];
            }
        }
        // 输出结果
        for (int n : nums) {
            System.out.print(n + " ");
        }
    }
}

 

插入排序:从后向前找到合适的位置后插入

基本思想:每步

我们取第一个数作为基准,找这个数的下一个数(4)。i为下标,从0开始。

第一轮:i=1,temp=4;拿4和34比,那么我们要把4插入到34前面,那么需要34向后挪,最后4是从temp中取出。

第二轮:i=2,temp=56;结果:4,34,56,17,90,65;由于34本身就比56小,所以不需要向前插入。注意向前比较的时候如果比较一次满足,那么久不需要再向前继续比较。

第三路:i=3;temp=17;17和56比;4,34,56,56,90,65;4,34,34,56,90,65;最后将17放在第二个位置,结果为4,17,34,56,90,65

第四轮:i=4;temp=90;不需要挪,因为90比56大。

第五轮:i=5;temp=65;65和90比,90向后挪,65和56比大,不需要挪了。所以最后90向后挪,把temp里的65放在原来90的位置;结果4,17,34,56,65,90

代码:

public class InsertSort {
    public static void main(String[] args) {
        int[] nums = { 34, 4, 56, 17, 90, 65 };
        // 控制比较的轮数
        for (int i = 1; i < nums.length; i++) {// i从1开始表示从第二个元素向前插入
            int temp = nums[i];// 记录操作数
            int j = 0;
            for (j = i - 1; j >= 0; j--) {// j=i-1表示当前这个元素的前一个元素的下标,最多比较到第0的元素
                if (nums[j] > temp) {
                    nums[j + 1] = nums[j];// 将4的位置赋值为34
                } else {
                    break;
                }
            }
            if (nums[j + 1] != temp) {// 把0的位置赋值为4
                nums[j + 1] = temp;
            }
        }
        // 输出结果
        for (int n : nums) {
            System.out.print(n + " ");
        }
    }

}

 

 

归并排序:是很有意义的经典算法

就是把两个已经排序好的队列合成为一个有序队列。就是将两个有序队列合并为一个有序队列。

关键是怎样将两个有序队列归并为一个有序队列:

1.我们需要一个新的数组来存放排序好的队列,这个队列的大小为两个归并队列的和。

2.需要两个指针,分别指向两个队列的第一个元素。

3.将两个指针所指的位置的元素进行比较,将较小的放在新数组的第一个位置。然后移动相应的指针。

4.一个队列元素耗尽,则另一个队列剩余元素都拷贝到新队列尾部。

代码实现:

/**
 * 归并排序:将两个有序数组合为一个有序数组
 *
 * @author Alisa
 *
 */
public class SSort {

    public static void main(String[] args) {
        int[] a = { 5, 8, 11, 19, 22, 25 };
        int[] b = { 7, 9, 20, 30, 35, 38, 40 };

        int[] c = merge(a, b);
        for (int i = 0; i < c.length; i++) {
            System.out.print(c[i] + " ");
        }
    }

    private static int[] merge(int[] a, int[] b) {
        //
        int[] x = new int[a.length + b.length];
        int ai = 0;
        int bi = 0;
        int xi = 0;// 记录当前已经放到了第几个元素
        // 添加一个循环,表示任何一方耗尽就停止
        while (ai < a.length && bi < b.length) {
            if (a[ai] <= b[bi]) {
                x[xi++] = a[ai++];
            } else {
                x[xi++] = b[bi++];
            }

        }
        // 此时表示至少有一方数组结束
        while (ai < a.length) {
            x[xi++] = a[ai++];
        }
        while (bi < b.length) {
            x[xi++] = b[bi++];
        }
        return x;
    }
}

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值