これは本当にプログラミング言語であるため、実際には、小さなシリーズは、あまりにも多くの人々 、数多くのオンラインのブログではなく、ホイールを作成繰り返す必要を使用することになり、ジャワの関連記事を書きたいことはほとんどありませんが、言語は、Javaを使用しますが、多くの人々は、しかし、使用する、マスター、熟練した熟練したと冗談、あなたは能力のレベルに到達したい、小扁は言って、正式な開発会社は、Javaで堪能開発者の一握りを介して到達することができますそうXiaobianは、ここで直接比較的容量およびナレッジベースを持ち上げるあなたにいくつかを与える、単純なAPIをJavaのかについての文法をスキップするインタビューは、ソート、本当に、私は知らない、特に、使用されるかもしれない後に、そうではありません実際にソートの本当に小さな手書きは、私が思うに、各インタビュアーが見たいれるインタビューの中の質問の並べ替え、ビッグデータの実際の開発などのすべてが、各候補者は、ソートアルゴリズムを得ることができるかどうかである理由それの本質。
さて、各書き込みのブログは、ソートアルゴリズムとそのJava実装を紹介するいくつかの小さなシリーズを作成し、ナンセンス、自己検査の束を持っていますが、変更したくありませんでした。
1.バブルソート
原理:一つの要素が背景にある以前の一つの要素よりも大きい場合、最初の要素から始めて、それが隣接比較し、それらが入れ替わる置きます。
回路図:
コードの実装:
public static void main(String[] args) {
int arr[] = { 15, 16, 145, 91, 9, 5, 0 };
int temp1=0;
for(int i=0;i<arr.length-1;i++){ //控制循环次数:arr.length-1
for(int j=0;j<arr.length-i-1;j++){ //控制比较次数:arr.length-i-1
if(arr[j]>arr[j+1]){
temp1=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp1;
}
}
}
}
バブルソートの強化されたバージョン:
public static void main(String[] args) {
int arr[] = { 1,0,2,3,4,5,6,7,8 };
int temp1;
for(int i=0;i<arr.length-1;i++){ //控制循环次数:arr.length-1
boolean flag=true; //判断内层循环是否执行
for(int j=0;j<arr.length-i-1;j++){ //控制比较次数:arr.length-i-1
if(arr[j]>arr[j+1]){
temp1=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp1;
flag=false;
}
}
if(flag){ //如果内层循环的if一次都没有执行,说明已经排序结束
break;
}
}
2. [ソート
原理:彼は背中のすべての要素と比較される最初の位置から開始して、フロントは、彼らが場所を交換し、後者の場合よりも大きくなります。
回路図:
コードの実装:
public static void main(String[] args) {
int arr[] = { 45,15,48,9,3,65,22 };
for(int i=0;i<arr.length-1;i++){ //控制位置,从第一个位置开始,到倒数第二个位置
for(int j=i+1;j<arr.length;j++){ //当前位置的下一个位置开始,与后面的所有比较
if(arr[i]>arr[j]){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
3.挿入ソート
原理:前の要素よりも小さく、それはその要素の前で彼に挿入される場合は、2番目の要素位置から、彼は、彼の前の要素を比較します。
回路図:
コードの実装:
public static void main(String[] args) {
int arr[] = { 45, 15, 48, 9, 3, 65, 22 };
// 插入排序
int temp1;
for (int i = 1; i < arr.length; i++) { //从第二个数开始,一直到最后一个数
for (int j = 0; j < i; j++) { //i之前的所有数,全部比较
if (arr[i] < arr[j]) {
temp1 = arr[i];
for (int k = i; k > j; k--) { //将前面的数据把后面的覆盖,从j开始,一直到i
arr[k] = arr[k - 1];
}
arr[j] = temp1;
}
}
}
4.クイックソート
原理:先选取一个基准点,作用:基准点左侧小于基准点的数据 基准点右侧放的数据都是大于基准点的数据。基准点:最常用的基准点选第一个,最终一个大数组不停的进行查分 拆分的最终结果每个数组只有一个元素。
原理图:
解释:大循环中有两个循环,一个是从右往左,找比基准点小的,一个是从左往右找比基准点大的(找到之后,与基准点交换位置)。最终大循环,在left>=right时结束。
(2) 快排拆分:
解释:使用递归的方式,将数组左右两边一次次拆分,直到left>=right时,递归结束。
代码实现:
public class QuickSort {
public static void main(String[] args) {
int arr[]= {2,7,1,2,8,1,3,9,415,189,123};
sort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
public static void sort(int [] arr,int left ,int right) {
//递归的出口,当左侧==右侧
if(left>=right) {
return;
}
//获取基准点
int point=getPoint(arr,left,right);
//左边排序(递归)
sort(arr,left,point-1);
//右边排序(递归)
sort(arr,point+1,right);
}
public static int getPoint(int [] arr,int left ,int right) {
int key=arr[left];
while(left<right) {
//从右向左循环,只要右边的比基准点大,就继续循序
while(key<=arr[right]&&left<right) {
//每循环一次,right的索引向左移一个
right--;
}
//交换基准点的位置
arr[left]=arr[right];
//从左向右循环,只要左边的比基准点小,就继续循序
while(arr[left]<=key&&left<right) {
left++;
}
//交换基准点
arr[right]=arr[left];
}
//最后给基准点赋值
arr[left]=key;
return left;
}
}
注意:了解快速排序有助于了解MR的map-reduce过程,因为在MRmap阶段环形缓冲区满了之后,会将数据溢写到文件中,这个过程中就是使用了快速排序。
5. 计数排序
原理:对一个已有数组进行排序,那么就新建一个数组,数组长度为数组中元素的最大值+1。并把已有数组中的元素,对应上新建数组的下标,放入里面,新建数组的元素为,已有数组中元素的出现次数。
原理图:
解释:新创建一个数组,长度为需要排序的数组的最大值+1,遍历数组,将数组中的值分别找到新数组的索引,将索引处的元素+1,最后,遍历输出新数组的下标(只输出相应的值>0的下标,并且值为多少就输出几次)。
代码实现:
public class CountSort {
public static void main(String[] args) {
int arr[]= {2,7,1,2,8,1,3,9,415,189,123};
sort(arr,415);
System.out.println(Arrays.toString(arr));
}
public static void sort(int arr[],int max) {
int index=0;
int newarr[]=new int [max+1];
for(int i=0;i<arr.length;i++) {
newarr[arr[i]]++;
}
for(int i=0;i<newarr.length;i++) {
if(newarr[i]!=0) {
for(int j=0;j<newarr[i];j++) {
arr[index++]=i;
}
}
}
}
}
注意:了解计数排序,有助于了解hbase的布隆过滤器,布隆过滤器的特点就是,我说没有就没有,我说有不一定有(有一定的误判率)。
6. 归并排序(两路)
原理:複数のデータセットのソート順。(時間計算量:N * logN個)は
:ソート2つのステージを有するマージ
正規化は、1つだけの要素を設定する小さなデータの各々に設定されたデータを分割します。
正規化されたデータセットを達成します:
public static void chai(int arr[],int first,int last,int [] newarr) {
if(first>=last) {
return;
}
//找中间点
int mid=(first+last)/2;
//左边归
chai(arr,first,mid,newarr);
//右侧拆
chai(arr,mid+1,last,newarr);
//拆完之后并
meger(arr,first,last,mid,newarr);
}
そして、aは2つのデータのセットを注文した、大規模なデータセットにマージ命じました。
二つのデータセットを達成し、注文しました:
public int[] bing(int arr1[], int arr2[]) {
//创建一个最终结果的数组:长度为arr1和arr2长度之和
int newarr[] = new int[arr1.length+arr2.length];
//新数组的元素标记
int index=0;
//记录arr1和arr2的下标
int arr1_index=0;
int arr2_index=0;
//只要有一个数组,遍历结束,就停止循环
while(arr1_index<arr1.length&&arr2_index<arr2.length) {
//进行判断,将数据存储在新数组中
if(arr1[arr1_index]<arr2[arr2_index]) {
newarr[index++]=arr1[arr1_index++];
}else {
newarr[index++]=arr2[arr2_index++];
}
}
//可能是arr1没有遍历完全
while(arr1_index<arr1.length) {
newarr[index++]=arr1[arr1_index++];
}
//可能是arr2没有遍历完全
while(arr2_index<arr2.length) {
newarr[index++]=arr2[arr2_index++];
}
return newarr;
}
完全なコードを達成:
public class bingSort {
public static void main(String[] args) {
int arr[]= {1,8,7,6,11,2,4};
int newarr[]=new int[arr.length];
System.out.println(Arrays.toString(arr));
chai(arr,0,arr.length-1,newarr);
System.out.println(Arrays.toString(newarr));
}
//归
public static void chai(int arr[],int first,int last,int [] newarr) {
if(first>=last) {
return;
}
//找中间点
int mid=(first+last)/2;
//左边归
chai(arr,first,mid,newarr);
//右侧拆
chai(arr,mid+1,last,newarr);
//拆完之后并
meger(arr,first,last,mid,newarr);
}
/**
* 并
* @param arr 原数组
* @param first 开始位置
* @param last 结束位置
* @param mid 中间位置
* @param newarr 存放最终结果的数组
*/
public static void meger(int arr[],int first,int last,int mid,int [] newarr) {
//第一个数据集的起始下标
int arr1_start=first;
//第一个数据集的终止下标
int arr1_end=mid;
//第二个数据集的起始下标
int arr2_start=mid+1;
//第二个数据集的终止下标
int arr2_end=last;
int index=0;
while(arr1_start<=arr1_end&&arr2_start<=arr2_end) {
if(arr[arr1_start]<arr[arr2_start]) {
newarr[index++]=arr[arr1_start++];
}else {
newarr[index++]=arr[arr2_start++];
}
}
while(arr1_start<=arr1_end) {
newarr[index++]=arr[arr1_start++];
}
while(arr2_start<=arr2_end) {
newarr[index++]=arr[arr2_start++];
}
/**
* 因为归并排序,需要使用两个有序的数据集,而arr一开始时无需的,所有每一次归并的时候
* 需要将归并好之后的那一段数据集,赋值到arr中,使之后的归并仍然有序
*/
//赋值的循环的次数,是本次归并的元素的个数
for(int i=0;i<index;i++) {
//每次赋值的时候,是从first开始
arr[first+i]=newarr[i];
}
}
}
注意:マージを使用するには、2つの相が存在するMRプログラムでは、小さなファイルを書き込みバッファオーバーフローがあり、最終的には一つの大きなファイルに複数の小さなファイルをマージします、他のプロセスである私にマップを持っ減らしますローカルデータは、小さなたくさんのファイルを生成することで、この時間は、マージを行います。
7.バイナリ検索データ
原則:財団は、配列の要素のバイナリ検索にソートされています。
回路図:
コードの実装:
public static void main(String[] args) {
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
// 二分法查数据
int num = new Scanner(System.in).nextInt(); //查找的数
int start = 0;
int end = arr.length - 1;
int middle = (start + end) / 2;
while (true) {
//如果end<start说明全部找完也没有找到
if (end < start) {
System.out.println(num + "不在此数组中");
break;
}
if (arr[middle] > num) {
end = middle - 1;
} else if (arr[middle] < num) {
start = middle + 1;
} else {
System.out.println("这个数的索引下标为" + middle);
break;
}
middle = (start + end) / 2;
}