2021-07-01排序算法

掌握算法是作为程序员的基本必备素质,而排序也是各种算法的基础,虽说java帮我们封装好了各种数据类型的排序方法,可是我们还是要知道他的原理,下面我就说几种常用的算法及原理;

冒泡排序:

原理:相邻元素两两比较,大的往后放,每一次完毕,最大值出现在了最大索引处;
下面我们用图的方式直观的给大家展示
在这里插入图片描述
从上面的图来看,每一次比较交换的算法应该是

/for(int i=0;i<arr.length-1;i++){
 		if(arr[i]>arr[i+1]){
    			//值交换
       			 int t=arr[i];
 				 arr[i]=arr[i+1];
				 arr[i+1]=t;
		  }
}

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

首次比较五个数我们只需要比较四次;每多一次排序,少比较一次,因此i<arr.length-1;而这个过程我们需要五次的重复,每次我们给循环条件 -1;而这也是可以简化的,所以最后我们优化过后的算法为:

private static void sort(int[] arr) {
        for(int j=0;j<arr.length;j++){
            for (int i = 0; i <  arr.length - 1 -j ; i++) {
                if (arr[i] > arr[i + 1]) {
                    //值交换
                    int t = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = t;
                }
            }
        }
  }

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

选择排序:

原理:每一次那一个元素,和剩余的元素挨个去比较,经过第一遍比较,那么最小的元素,或移动到最前面去;
在这里插入图片描述

 for (int i = index + 1; i < arr.length; i++) {
                if (arr[index] > arr[i]) {
                	//值交换
                    int t = arr[index];
                    arr[index] = arr[i];
                    arr[i] = t;
                }
            }

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

选择排序就是每次选择一个数和其余的数一一进行比较,比他大的不动,比他小的两者交换;第一次我们就是选择第一个数为基准,它作为index和其余的比较,而我们第一个比较的数就是第二个数,应为自己和自己比较并没有意义;然后循环比较,每次变量 +1;以上的只是第一次比较,当比较完后,我们换第二个数为基准,即index+1;所以我们将其优化为:

private static void sort2(int[] arr) {
        for (int index = 0; index < arr.length - 1; index++) {
            for (int i = index + 1; i < arr.length; i++) {
                if (arr[index] > arr[i]) {
                    int t = arr[index];
                    arr[index] = arr[i];
                    arr[i] = t;
                }
            }
        }
    }

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在外围再加一层循环,它起到的作用就是每次比较过后index自加;


快速排序:

原理:快速排序的原理就是分治法;即先比大小,再分区,然后分而治之;
从数组中取出一个数,作为基准;然后分区,选择出比这个数大的数放到它的右边,比这个数小的数放到他的左边;然后分别对左右分区进行分区,直到每个分区只剩一个数;
而他的实现思想可以叫做挖坑填数;什么意思呢?
1.将基准数挖出,形成坑位一;
2.先从后向前找比基准数小的数,找到后挖出它,形成新坑位,将它填到之前的坑位中;
3.然后由前向后找比基准数大的数,找到后挖出它,将他填到之前的坑位中;
4.分号区后,重复之前的2、3步骤;

第一次分析挖坑填数后的结果如下图:
在这里插入图片描述
代码实现:
首先我们需要给序列的起始位置和末尾位置,以此确定每次从前向后和从后向前比较的起点;
int i = start;
int j = end;
然后定义基准位置;
int x =arr[i];
最外围的循环条件为i < j,即起点位置小于终点位置,因为我们最后如果起点位置和终点位置一样时,每个分区就只剩一个数了,这样就完成了排序;同时我们不知道这个过程需要循环多少次,于是用while()循环方法;
while(i < j){}
然后我们就分开从左到右和从右到左的两部分;
从后往前:
while (i<j&&arr[j]>x){
j–;
}
if(i<j){
arr[i]=arr[j];//挖坑填数
i++; //因为接下来我们要从前往后找了,我们顺遍让i递增一下
}
从前往后:
while (i < j && arr[i] <= x) {
i++;
}
if (i < j) {
arr[j] = arr[i];//挖坑填数
j–; //因为接下来我们要从后往前找了,我们顺遍让j递减一下
}
最后我们把基准数填到最后的位置:
arr[i]=x;
同时返回基准数的位置,return i;

我们得到分区完后,基准数的左边的数为左分区的end,基准数的右边的数作为右分区的start;

因此最后我们得到的代码为:

public class QuickSort {
public <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">sort</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> arr<span class="token punctuation">,</span><span class="token keyword">int</span> start<span class="token punctuation">,</span><span class="token keyword">int</span> end<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>start<span class="token operator">&lt;</span>end<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
        <span class="token comment">//获取中间索引</span>
        <span class="token keyword">int</span> index<span class="token operator">=</span><span class="token function">getIndex</span><span class="token punctuation">(</span>arr<span class="token punctuation">,</span>start<span class="token punctuation">,</span>end<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">//对左右两部分进行递归调用</span>
        <span class="token function">sort</span><span class="token punctuation">(</span>arr<span class="token punctuation">,</span>start<span class="token punctuation">,</span>index<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//排左半边</span>
        <span class="token function">sort</span><span class="token punctuation">(</span>arr<span class="token punctuation">,</span>index<span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">,</span>end<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//排右半边</span>

    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">//挖坑填数</span>
private <span class="token keyword">static</span> <span class="token keyword">int</span> <span class="token function">getIndex</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> arr<span class="token punctuation">,</span> <span class="token keyword">int</span> start<span class="token punctuation">,</span> <span class="token keyword">int</span> end<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token keyword">int</span> i<span class="token operator">=</span>start<span class="token punctuation">;</span>
        <span class="token keyword">int</span> j<span class="token operator">=</span>end<span class="token punctuation">;</span>
        <span class="token comment">//定义基准数</span>
        <span class="token keyword">int</span> x<span class="token operator">=</span>arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>
        <span class="token keyword">while</span> <span class="token punctuation">(</span>i<span class="token operator">&lt;</span>j<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
            <span class="token comment">//1.从后往前跟基准数进行比较</span>
            <span class="token keyword">while</span> <span class="token punctuation">(</span>i<span class="token operator">&lt;</span>j<span class="token operator">&amp;&amp;</span>arr<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">&gt;=</span> x<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
                j<span class="token operator">--</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
            <span class="token keyword">if</span><span class="token punctuation">(</span>i<span class="token operator">&lt;</span>j<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
                arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">=</span>arr<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token comment">//挖坑填数</span>
                i<span class="token operator">++</span><span class="token punctuation">;</span><span class="token comment">//因为接下来我们要从前往后找了,我们顺遍让i递增一下</span>
            <span class="token punctuation">}</span>
            <span class="token comment">//2.从前往后找</span>
            <span class="token keyword">while</span> <span class="token punctuation">(</span>i <span class="token operator">&lt;</span> j <span class="token operator">&amp;&amp;</span> arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">&lt;=</span> x<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                i<span class="token operator">++</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>i <span class="token operator">&lt;</span> j<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                arr<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token comment">//挖坑填数</span>
                j<span class="token operator">--</span><span class="token punctuation">;</span><span class="token comment">//因为接下来我们要从后往前找了,我们顺遍让j递减一下</span>
            <span class="token punctuation">}</span>

        <span class="token punctuation">}</span>
        <span class="token comment">//把基准数填到最后一个坑位</span>
        arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">=</span>x<span class="token punctuation">;</span>

    <span class="token keyword">return</span> i<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

二分法查找:

注:二分法查找的前提是元素有序;
原理:每次都查中间的那个元素,比较大或者小就能减少一半的元素;
在这里插入图片描述
代码实现:
首先我们定义三个位置的变量:
int minIndex=0;
int maxIndex=arr.length-1;
int midIndex=(minIndex+maxIndex)/2;
最外围循环则是最小值小于最大值
minIndex < maxIndex;
如果要查的元素,正好等于中间索引所对应的元素 直接返回这个中间索引;
if (ele == arr[midIndex]) {
return midIndex;
}
如果你要查找的元素比中间索引所对应的元素大 那么就动最小索引
if (ele > arr[midIndex]) {
minIndex = midIndex + 1;
}
如果你要查找的元素比中间索引所对应的元素小,那么你就动最大索引
if (ele < arr[midIndex]) {
maxIndex = midIndex - 1;
}
最后重新计算中间的索引
midIndex = (minIndex + maxIndex) / 2;

所以最后的代码就是:

private static int findIndex2(int[] arr, int ele) {
        int minIndex=0;
        int maxIndex=arr.length-1;
        int midIndex=(minIndex+maxIndex)/2;
        while (minIndex < maxIndex){
            //如果要查的元素,正好等于中间索引所对应的元素 直接返回这个中间索引
            if (ele == arr[midIndex]) {
                return midIndex;
                //如果你要查找的元素比中间索引所对应的元素大 那么就动最小索引
            } else if (ele > arr[midIndex]) {
            minIndex <span class="token operator">=</span> midIndex <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span>
            <span class="token comment">//如果你要查找的元素比中间索引所对应的元素小,那么你就动最大索引</span>
        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>ele <span class="token operator">&lt;</span> arr<span class="token punctuation">[</span>midIndex<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
            maxIndex <span class="token operator">=</span> midIndex <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token comment">//再重新计算中间索引</span>
        midIndex <span class="token operator">=</span> <span class="token punctuation">(</span>minIndex <span class="token operator">+</span> maxIndex<span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值