java基数排序 数组_万字长文带你掌握Java数组与排序,代码实现原理都帮你搞明白!...
查找元素索引位置
基本查找
根據數組元素找出該元素第一次在數組中出現的索引
public class TestArray1 {
public static void main(String[] args) {
//定義一個數組
int[] arr={10,20,70,10,90,100,1,2};
//根據元素查找出該元素在數組中第一次出現的索引
int index=getIndexByEle(arr,2);
System.out.println("該元素第一次在數組中出現的索引是:"+index);
}
private static int getIndexByEle(int[] arr, int ele) {
//遍歷數組,去查找
for (int i = 0; i < arr.length; i++) {
if (ele==arr[i]){
return i;
}
}
return -1;//如果我們沒有找到這個元素那么就返回-1
}
}
案例中查找元素2的索引,索引為7;
運行后返回結果正確:
二分查找
使用二分查找查找出該元素在數組中第一次出現的索引
前提:該數組的元素必須有序
思想:每一次都查找中間的元素,比較大小就能減少一半的元素
具體代碼實現:
public class TestArray2 {
public static void main(String[] args) {
//二分查找:前提是數組元素必須有序
int[] arr={10,20,30,40,50,60,70,80,90};
int index=getIndexByEle(arr,40);
System.out.println("該元素的索引是:"+index);
}
private static int getIndexByEle(int[] arr, int ele) {
//定義最小索引,中間索引,最大索引
int minIndex=0;
int maxIndex=arr.length-1;
int centerIndex=(minIndex+maxIndex)/2;
while (minIndex<=maxIndex){
//如果需查找元素等于中間索引所對應元素,返回中間元素,表示找到
if (ele==arr[centerIndex]){
return centerIndex;
}
//如果需查找元素大于中間索引所對應元素,移動最小索引至中間索引處
else if (ele>arr[centerIndex]){
minIndex=centerIndex+1;
}
//如果需查找元素小于中間索引所對應元素,移動最大索引至中間索引處
else if (ele
maxIndex=centerIndex-1;
}
//重新計算中間索索引
centerIndex=(minIndex+maxIndex)/2;
}
return -1;//如果沒有找到,就返回-1
}
}
案例中查找元素為40,索引為3;
運行后返回結果正確:
八大排序方法
冒泡排序
原理:數組元素兩兩比較,交換位置,大元素往后放,經過一輪比較后,最大的元素,就會被排到數組的最后
圖解:
代碼部分:
先進行第一輪排序,看看效果:
public class ArraySort1 {
public static void main(String[] args) {
//原理:數組元素兩兩比較,前面元素大于后面元素則交換,否則不交換,每經過一輪,最大的元素會排到最后
int[] arr={24,69,80,57,13};
//第一輪比較,遍歷數組
for (int i = 0; i < arr.length-1; i++) {
//從從第0個元素開始,前一個元素與后一個元素比較
if (arr[i]>arr[i+1]){
//滿足條件則交換位置,利用temp中間變量寄存元素
int temp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=temp;
}
}
//輸出數組
System.out.println(Arrays.toString(arr));
}
}
下面進行多輪排序:
代碼部分
笨方法:多次for循環,比較繁瑣,重復循環,語句沒營養,看看就好,主要是得能想到,為嵌套循環做準備
public class ArraySort1 {
public static void main(String[] args) {
//原理:數組元素兩兩比較,前面元素大于后面元素則交換,否則不交換,每經過一輪,最大的元素會排到最后
int[] arr={24,69,80,57,13};
//第一輪比較,遍歷數組
for (int i = 0; i < arr.length-1; i++) {
//從從第0個元素開始,前一個元素與后一個元素比較
if (arr[i]>arr[i+1]){
//滿足條件則交換位置,利用temp中間變量寄存元素
int temp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=temp;
}
}
//輸出數組
System.out.println(Arrays.toString(arr));
//第二輪比較,遍歷數組
for (int i = 0; i < arr.length-1-1; i++) {
if (arr[i]>arr[i+1]){
int temp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=temp;
}
}
//輸出數組
System.out.println(Arrays.toString(arr));
//第三輪比較,遍歷數組
for (int i = 0; i < arr.length-1-1-1; i++) {
if (arr[i]>arr[i+1]){
int temp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=temp;
}
}
//輸出數組
System.out.println(Arrays.toString(arr));
//第四輪比較,遍歷數組
for (int i = 0; i < arr.length-1-1-1-1; i++) {
if (arr[i]>arr[i+1]){
int temp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=temp;
}
}
//輸出數組
System.out.println(Arrays.toString(arr));
}
}
使用嵌套循環(語句精簡,沒有廢話):
public class ArraySort1 {
public static void main(String[] args) {
//原理:數組元素兩兩比較,前面元素大于后面元素則交換,否則不交換,每經過一輪,最大的元素會排到最后
int[] arr={24,69,80,57,13};
//嵌套for循環,外層循環輪數,內層對每一輪內元素進行比較
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length-1-i; j++) {
if (arr[j]>arr[j+1]){
//交換位置
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
冒泡排序就介紹到這里~~~
選擇排序
原理:從0索引處開始,依次和后面的元素進行比較,小的元素往前放,經過一輪比較后,最小的元素就會出現在最小索引處
圖解:
代碼部分:多輪排序(優化前)
public class ArraySort2 {
public static void main(String[] args) {
//原理:從0索引處開始,依次個后面的元素進行比較,小的元素往前放,經過一輪比較,最小的元素就出現在最小索引處
int[] arr={24,69,80,57,13};
//第一輪比較,從0索引處開始比
int index=0;
for (int i = 1; i < arr.length; i++) {
if (arr[index]>arr[i]){
int temp=arr[index];
arr[index]=arr[i];
arr[i]=temp;
}
}
System.out.println(Arrays.toString(arr));
//第二輪
index=1;
for (int i = 1+index; i < arr.length; i++) {
if (arr[index]>arr[i]){
int temp=arr[index];
arr[index]=arr[i];
arr[i]=temp;
}
}
System.out.println(Arrays.toString(arr));
//第三輪
index=2;
for (int i = 1+index; i < arr.length; i++) {
if (arr[index]>arr[i]){
int temp=arr[index];
arr[index]=arr[i];
arr[i]=temp;
}
}
System.out.println(Arrays.toString(arr));
//第四輪
index=3;
for (int i = 1+index; i < arr.length; i++) {
if (arr[index]>arr[i]){
int temp=arr[index];
arr[index]=arr[i];
arr[i]=temp;
}
}
System.out.println(Arrays.toString(arr));
}
}
優化代碼:嵌套循環:
public class ArraySort2 {
public static void main(String[] args) {
//原理:從0索引處開始,依次個后面的元素進行比較,小的元素往前放,經過一輪比較,最小的元素就出現在最小索引處
int[] arr={24,69,80,57,13};
//第一輪比較,從0索引處開始比
for (int index = 0; index < arr.length-1; index++) {
for (int i = 1+index; i < arr.length; i++) {
if (arr[index]>arr[i]){
int temp=arr[index];
arr[index]=arr[i];
arr[i]=temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
選擇排序就介紹到這里~~~
直接插入排序
原理:從1索引處開始,將后面的元素與前一位比,小于前一位則交換,再與前一位比,如果小于再交換,如此循環,插入之前的有序列表中使之仍保持有序
(方法1):代碼實現:
public class ArraySort3 {
public static void main(String[] args) {
//直接插入排序:從1索引處開始,將后面的元素,插入之前的有序列表中使之仍保持有序
int[] arr={3,2,1,0,10,20,30,7,8};
//外層循環定義輪次
for (int i = 1; i < arr.length; i++) {
//內層循環進行比較插入
int j=i;
while (j>0 && arr[j]
int temp=arr[j];
arr[j]=arr[j-1];
arr[j-1]=temp;
j--;
}
}
System.out.println(Arrays.toString(arr));
}
}
(方法2)代碼實現:
public class ArraySort3 {
public static void main(String[] args) {
//直接插入排序:從1索引處開始,將后面的元素,插入之前的有序列表中使之仍保持有序
int[] arr={3,2,1,0,10,20,30,7,8};
//外層循環定義輪次
for (int i = 0; i < arr.length; i++) {
for (int j = i; j >0 ; j--) {
if (arr[j]
int temp=arr[j];
arr[j]=arr[j-1];
arr[j-1]=temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
由于很多地方需要使用前后元素值交換,因此封裝成一個方法:代碼如下:
public static void swapValue(int[] arr,int i,int j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
使用自己封裝的方法:
for (int i = 0; i < arr.length; i++) {
for (int j = i; j >0 ; j--) {
if (arr[j]
/*
int temp=arr[j];
arr[j]=arr[j-1];
arr[j-1]=temp;
*/
//直接調用交換方法,封裝思想
swapValue(arr,j,j-1);
}
}
}
直接插入排序就介紹到這里~~~
希爾排序
希爾排序又稱縮小增量排序
基本思想:先將原表按增量ht分組;每個子文件按照直接插入法排序。同樣,用下一個增量ht/2將文件再分為自問見,在直接插入法排序。直到ht=1時整個文件排好序。
關鍵:選擇合適的增量。
希爾排序算法9-3:可以通過三重循環來實現。
圖示:
將數組按步長為5的間隔兩兩分為一組,每組兩個元素進行比較大小,小的放置于前面,大的放置于后面;
由此排序一次后,大致可以將整個數組中較小的元素放在前面,較大的放在后面。
下面數組長度為8,第一次間隔取4,第二次間隔取2,第三次間隔取1,具體實現見下圖:
代碼實現(使用克努特序列,合理選擇增量):
public class ArraySort4 {
public static void main(String[] args) {
//希爾排序,對插入排序的優化,核心思想就是合理的選取增量,經過一輪排序后,就會讓序列大致有序
//然后不斷的縮小增量,進行插入排序,直到增量為1整個排序結束
//直接插入排序,其實就是增量為1的希爾排序
int[] arr={46,55,13,43,17,94,5,70,11,25,110,234,1,3,66};
shellSort(arr);
System.out.println(Arrays.toString(arr));
}
private static void shellSort(int[] arr) {
//定義一個增量
/*
//第一輪
int h=4;
for (int i = h; i < arr.length; i++) {
for (int j = i; j > h-1 ; j-=h) {
if (arr[j]
swapValue(arr,j,j-h);
}
}
}
//第二輪
h=2;
for (int i = h; i < arr.length; i++) {
for (int j = i; j > h-1 ; j-=h) {
if (arr[j]
swapValue(arr,j,j-h);
}
}
}
//第三輪
h=1;
for (int i = h; i < arr.length; i++) {
for (int j = i; j > h-1 ; j-=h) {
if (arr[j]
swapValue(arr,j,j-h);
}
}
}
*/
//希爾排序核心代碼
//希爾排序的思想,合理的選取增量
//第一次增量可以選取數組長度的一半,然后不斷的減半
/*for (int h = arr.length / 2; h > 0; h /= 2) {
for (int i = h; i < arr.length; i++) {
for (int j = i; j > h - 1; j -= h) {
if (arr[j] < arr[j - h]) {
swapValue(arr, j, j - h);
}
}
}
}*/
//增量的選取選擇數組長度的一半,還不是很合理,我們可以使用一種序列,叫做克努特序列
//int h = 1;
//h = h * 3 + 1; //1,4,13,40,121,364
//根據克努特序列選取我們的第一次增量
int jiange = 1;
while (jiange <= arr.length / 3) {
jiange = jiange * 3 + 1;
}
for (int h = jiange; h > 0; h = (h - 1) / 3) {
for (int i = h; i < arr.length; i++) {
for (int j = i; j > h - 1; j -= h) {
if (arr[j] < arr[j - h]) {
swapValue(arr, j, j - h);
}
}
}
}
}
//封裝元素交換方法
public static void swapValue(int[] arr,int i,int j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
希爾排序就介紹到這里~~~
快速排序
原理:分治法:比大小,再分區
從數組中取出一個數,作為基準數
分區:將比這個數大或等于的書全放到他的右邊,小于他的數全放到他的左邊。
再對左右區間重復第二步,直到各區間只有一個數。
實現思路
將基準數挖出形成第一個坑
由后向前找比它小的數,找到后挖出此數填到前一個坑中
由前向后找比它大或等于的數,找到后也挖出此數填到前一個坑中。
再重復執行上述兩步驟
代碼實現:
public class ArraySort5 {
public static void main(String[] args) {
//定義一個數組
int[] arr={10,3,34,45,11,35,255,4,-1,-9,79,123};
quickSort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
//快速排序
public static void quickSort(int[] arr,int start,int end) {
//找出分左右兩區的索引位置,然后對左右兩區進行遞歸調用
if (start
int index=getIndex(arr,start,end);
quickSort(arr,start,index-1);
quickSort(arr,index+1,end);
}
}
//將基準數挖出形成第一個坑
//由后向前找比它小的數,找到后挖出此數填到前一個坑中
//由前向后找比它大或等于的數,找到后也挖出此數填到前一個坑中。
//再重復執行上述兩步驟
private static int getIndex(int[] arr, int start, int end) {
int i=start;
int j=end;
int x=arr[i];
while (i
//由后向前找比它小的數,找到后挖出此數填到前一個坑中
while (i=x){
j--;
}
if (i
arr[i]=arr[j];
i++;
}
//由前向后找比它大或等于的數,找到后也挖出此數填到前一個坑中。
while (i
i++;
}
if (i
arr[j]=arr[i];
j--;
}
}
arr[i]=x;//把基準數填到最后一個坑
return i;
}
}
快速排序就介紹到這里~~~
歸并排序
歸并排序(Merge Sort)就是利用歸并的思想實現排序的方法
原理:假設初始序列有N個記錄,則可以看成是N個有序的子序列,每個子序列的長度為1,然后兩兩歸并,得到N/2個長度為2或1的有序子序列,再兩兩歸并。。。如此重復,直至得到一個長度為N的有序序列為止,這種排序方法稱為2路歸并排序
代碼實現:
public class ArraySort6 {
public static void main(String[] args) {
//原始待排序數組
int[] arr={10,23,1,43,0,-3,1121,343,44,11,56,78,3,-1};
//我們先給一個左右兩邊是有序的一個數組,先來進行歸并操作
//int[] arr={4,5,7,8,1,2,3,6};
//拆分
chaifen(arr,0,arr.length-1);
//歸并
guiBing(arr,0,3,arr.length-1);
//輸出原數組
System.out.println(Arrays.toString(arr));
}
private static void chaifen(int[] arr, int startIndex, int endIndex) {
//計算中間索引
int centerIndex=(startIndex+endIndex)/2;
if (startIndex
chaifen(arr,startIndex,centerIndex);
chaifen(arr,centerIndex+1,endIndex);
guiBing(arr,startIndex,centerIndex,endIndex);
}
}
private static void guiBing(int[] arr, int startIndex, int centerIndex, int enIndex) {
//定義一個臨時數組
int[] tempArr=new int[enIndex-startIndex+1];
//定義左邊數組的起始索引
int i=startIndex;
//定義右邊數組的起始索引
int j=centerIndex+1;
//定義臨時數組的起始索引
int index=0;
while (i<=centerIndex && j<=enIndex){
if (arr[i]<=arr[j]){
tempArr[index]=arr[i];
i++;
}else{
tempArr[index]=arr[j];
j++;
}
index++;
}
//處理剩余元素
while (i<=centerIndex){
tempArr[index]=arr[i];
i++;
index++;
}
while (j<=enIndex){
tempArr[index]=arr[j];
j++;
index++;
}
//將臨時數組中的元素取到原數組中
for (int k = 0; k < tempArr.length; k++) {
arr[k+startIndex]=tempArr[k];
}
}
}
歸并排序就介紹到這里~~~
基數排序
基數排序不同于之前的各類排序
前面的排序或多或少通過使用比較和移動記錄來實現排序
而基數排序的實現不需要進行對關鍵字的比較,只需要對關鍵字進行“分配”與“收集”兩種操作即可完成
下面通過圖來解釋:
第一次排序:按照個位進行分組
分組后結果:
再將元素逐一取出:
第二次排序:根據十位上的數進行排序
再依次將元素取出:
第三輪排序:根據百位上的數進行排序
最后將所有元素取出:
代碼實現:
public class ArraySort7 {
public static void main(String[] args) {
//基數排序:通過分配再收集的方式進行排序
int[] arr={2,0,1,5,21,31,224,355,22,41,67,23,444,789,12,55,34,75};
//確定排序輪次
//獲取數組中的最大值
int max=getMax(arr);
//基數排序
sortArray(arr);
//輸出排序后的數組
System.out.println(Arrays.toString(arr));
}
private static void sortArray(int[] arr) {
//定義二維數組,放10個桶
int[][] tempArr=new int[10][arr.length];
//定義統計數組
int[] counts=new int[10];
int max=getMax(arr);
int len=String.valueOf(max).length();
//循環輪次
for (int i = 0,n=1; i < len; i++,n*=10) {
for (int j = 0; j < arr.length; j++) {
//獲取每個位上的數字
int ys=arr[j]/n%10;
tempArr[ys][counts[ys]++]=arr[j];
}
//取出桶中的元素
int index=0;
for (int k = 0; k < counts.length; k++) {
if (counts[k]!=0){
for (int h = 0; h < counts[k]; h++) {
//從桶中取出元素放回原數組
arr[index]=tempArr[k][h];
index++;
}
counts[k]=0;//清除上一次統計的個數
}
}
}
}
private static int getMax(int[] arr) {
int max=arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i]>max){
max=arr[i];
}
}
return max;
}
}
基數排序就介紹到這里~~~
堆排序
堆排序是利用堆這種數據結構而設計的一種排序算法,堆排序是一種選擇排序
將待排序序列構造成一個大頂堆,此時,整個序列的最大值就是堆頂的根節點。
將其與末尾元素進行交換,此時末尾就為最大值
然后將剩余n-1個元素重新構造成一個堆,這樣就會得到n個元素的次小值
如此反復的執行,便能得到一個有序序列了
代碼實現:
public class ArraySort8 {
public static void main(String[] args) {
//定義一個數組
int[] arr={1,0,6,7,2,3,4,5,8,9,10,52,12,33};
//調整成大頂堆的方法
//定義開始調整的位置
int startIndex=(arr.length-1)/2;
//循環開始調
for (int i = startIndex; i >=0 ; i--) {
toMaxHeap(arr,arr.length,i);
}
//System.out.println(Arrays.toString(arr));
//經過上面的操作后,已經把數組變成一個大頂堆,把根元素和最后一個元素進行調換
for (int i = arr.length-1; i >0; i--) {
//進行調換
int temp=arr[0];
arr[0]=arr[i];
arr[i]=temp;
//換完之后,我們再把剩余元素調成大頂堆
toMaxHeap(arr,i,0);
}
System.out.println(Arrays.toString(arr));
}
/**
*
* @param arr 要排序的數組
* @param size 調整的元素個數
* @param index 從哪里開始調整
*/
private static void toMaxHeap(int[] arr, int size, int index) {
//獲取左右字節的索引
int leftNodeIndex=index*2+1;
int rightNodeIndex=index*2+2;
//查找最大節點所對應的索引
int maxIndex=index;
if (leftNodeIndexarr[maxIndex]){
maxIndex=leftNodeIndex;
}
if(rightNodeIndexarr[maxIndex]){
maxIndex=rightNodeIndex;
}
//我們來調換位置
if(maxIndex!=index){
int t=arr[maxIndex];
arr[maxIndex]=arr[index];
arr[index]=t;
//調換完之后,可能會影響到下面的子樹,不是大頂堆,我們還需要再次調換
toMaxHeap(arr,size,maxIndex);
}
}
}
堆排序就介紹到這里~~~
最后
感謝你看到這里,文章有什么不足還請指正,覺得文章對你有幫助的話記得給我點個贊,每天都會分享java相關技術文章或行業資訊,歡迎大家關注和轉發文章!
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的java基数排序 数组_万字长文带你掌握Java数组与排序,代码实现原理都帮你搞明白!...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: riak文件服务器,Docker中文文档
- 下一篇: java美元兑换,(Java实现) 美元