掌握算法是作为程序员的基本必备素质,而排序也是各种算法的基础,虽说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"><</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"><</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"><</span>j<span class="token operator">&&</span>arr<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">>=</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"><</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"><</span> j <span class="token operator">&&</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 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"><</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"><</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