java 算法 排序算法_Java七种排序算法以及实现
Java常見七種排序算法以及實現
最近學習一些排序算法,怕自己以后忘記就打算整理起來供自己復習
萌新一枚學習Java沒多久,以下僅供參考。如有錯誤希望大佬指正,歡迎大家在評論區交流探討。
1.冒泡排序
通過待排序的序列從前往后依次比較相鄰的元素,若發現逆序則兩兩交換,直到下一趟排序下來沒有進行交換,說明排序完成
冒泡排序每一趟會確定一個最大值(默認從小到大)
import java.util.Arrays;
public class BubbleSort {
public static void main(String[] args) {
int array[] = {10,9,2,-3,6,8,1,-6,-5,4};
for (int i = 0; i < array.length ; i++) { //循環每一趟排序
for (int j = 0; j < array.length-1-i ; j++) {
// 每一趟排序的數據交換
// 由于array[j]是和array[j+1]比較,防止數據越界這里array.length要減一
int temp = 0;
if (array[j]>array[j+1]){
temp = array[j+1];
array[j+1] = array[j];
array[j] = temp;
}
}
}
// 兩種方法輸出
// 1.格式化輸出,需import,之后的代碼演示全用格式化輸出
System.out.println(Arrays.toString(array));
// 2.for循環輸出
for (int i = 0; i < array.length ; i++) {
System.out.print(array[i]+" ");
}
}
}
2.選擇排序
第一趟排序是從array[0]到array[array.length-1]找到一個最小值array[n]與array[0]進行交換,第一趟排序是從array[1]到array[array.length-1]找到一個最小值array[n]與array[1]進行交換,直到排序完成
選擇排序每一趟排序會確定一個最小值(默認從小到大)
以下是三種不同的代碼實現
import java.util.Arrays;
public class SelectSortDemo01 {
public static void main(String[] args) {
int array[] = {10,9,2,-3,6,8,1,-6,-5,4};
for (int i = 0; i < array.length-1 ; i++) {
for (int j = 1+i; j < array.length; j++) {
// 此算法與冒泡排序的算法類似,只不過冒泡算法的每一趟排序是兩兩比較,這個是第一個數與每一個數比較
int temp = 0;
if (array[i] > array[j]){
temp = array[j];
array[j] = array[i];
array[i] = temp;
}
}
}
System.out.println(Arrays.toString(array));
}
}
import java.util.Arrays;
public class SelectSortDemo02 {
public static void main(String[] args) {
int array[] = {10,9,2,-3,6,8,1,-6,-5,4};
int temp = 0;
for (int j = 0; j
for (int i = 1; (i+j)< array.length ; i++) {
//此算法與上面一個大同小異,也實現了相同的效果,可以根據自己的思維選擇一個合適的算法
if (array[j] > array[i+j]) {
temp = array[i+j];
array[i+j] = array[j];
array[j] = temp;
}
}
}
System.out.println(Arrays.toString(array));
}
}
12345678910111213141516171819
public class SelectSortDemo02 {
public static void main(String[] args) {
int array[] = {10,9,2,-3,6,8,1,-6,-5,4};
for (int i = 0; i < array.length-1 ; i++) {
// 與前面兩種方法不同的是此算法直接先假定每一趟排序的第i個數的數值最小,提取當前下標i,
// 方便每一趟排序與第i個數據進行交換
// 這樣也更容易理解
int min = array[i];
int minIndex = i;
for (int j = 1 + i; j < array.length; j++) {
if (min > array[j] ){
// 說明假定的最小值并不是最小的,需要重置min,此時只需賦值,不需要交換
// 讓其循環結束直到賦值到最小值
min = array[j];
minIndex = j;
}
}
// 將最小值放在arr[0],交換
if (minIndex != j) {
array[minIndex] = arr[j];
array[j] = min;
}
}
System.out.println(Arrays.toString(array));
}
}
123456789101112131415161718192021222324252627
3.插入排序
假如有n個數,第一趟排序就是比較前兩個數將它們排好(默認從小到大),然后在來一個數比較他們三個再排好
可以理解為斗地主的摸牌,先摸了兩張J和K,要把J放在K的前面,在摸一張6要放在J和K的前面,在摸一張10就要放在6和J之間,排摸完了就相當于排序結束
import java.util.Arrays;
public class InsertSortDemo01 {
public static void main(String[] args) {
int[] array = {5, 2, -1, 4, 7};
for (int i = 1; i < array.length; i++) {
// 與選擇排序第三種類似,先定義一個待插入的數據和插入的位置,便于之后賦值
int insertVal = array[i];
// 為了將待插入的數插入到array[i]的前一個位置
int insertIndex = i - 1;
// 待插入的位置必須大于等于0,保證數組不越界
while (insertIndex >= 0 && insertVal < array[insertIndex]) {
// 直接賦值不用交換數據
array[insertIndex + 1] = array[insertIndex];
// 為了讓第i個數與前面的數都進行比較然后賦值,前面有條件不用但不用擔心數組越界
insertIndex--;
}
// insertIndex + 1 = i 說明第i輪已經有序
if (insertIndex + 1 != i) {
array[insertIndex + 1] = insertVal;
}
}
System.out.println(Arrays.toString(array));
}
}
1234567891011121314151617181920212223242526
4.希爾排序
希爾排序相當于對插入排序進行優化,是一種縮小增量排序
希爾排序第一趟按照arraylength\2進行分組,每組分別進行直接插入排序,第二趟按照arraylength\2\2進行分組,每組分別進行直接插入排序,直到增量減至為一,整個文件恰好被分為一組
以下是兩種不同的代碼實現
import java.util.Arrays;
// 交換法,此實現方法速度是很慢,
// 因為插入排序比較之后直接移位,而此類方法一遇到逆序就會發生交換,
// 交換法與冒泡排序類似,不停的交換效率很低
public class ShellSortDemo02 {
public static void main(String[] args) {
int array[] = {10,9,2,-3,6,8,1,-6,-5,4};
int temp = 0;
for (int len = array.length/2; len > 0;len/=2) {
// 循環每一次分組
for (int i = len; i < array.length; i++) {
// 遍歷各組的所有元素,有len組
for (int j = i - len; j >= 0; j -= len) {
if (array[j] > array[j + len]) {
temp = array[j];
array[j] = array[j + len];
array[j + len] = temp;
}
}
}
}
System.out.println(Arrays.toString(array));
}
}
12345678910111213141516171819202122232425
import java.util.Arrays;
public class ShellSortDemo03 {
// 對交換式的希爾排序進行優化,采用移位法
// 當需要插入的數是最小數時,后移的次數明顯增多,所以使用分組插入排序會大大的提高效率
public static void main(String[] args) {
int[] array = {10, 9, 2, -3, 6, 8, 1, -6, -5, 4};
// 仍然使用增量len,并逐步縮小增量
for (int len = array.length / 2; len > 0; len /= 2) {
// 逐個對其所在的組進行直接插入排序
for (int i = len; i < array.length; i++) {
int j = i;
int temp = array[j];
if (array[j] < array[j - len]) {
while (j-len >= 0 && temp < array[j - len]) {
// 移動,與直接插入排序不同的是這個是間距len之間的數據移位,而直接插入排序是兩兩移位
array[j] = array[j - len];
j -=len;
}
// 當退出while循環后,就給temp找到了插入的位置
array[j] = temp;
}
}
}
System.out.println(Arrays.toString(array));
}
}
123456789101112131415161718192021222324252627
快速排序是一種對冒泡排序的改進,第一趟排序以中間的一個數為基準,將數組中比他小的數放在此數的左邊,比他大的數放在此數的右邊,第二趟排序以第一趟排好的左右的中間一個數為基準,在分別重復上面操作
import java.util.Arrays;
public class QuickSortDemo01 {
public static void main(String[] args) {
int array[] = {10,9,2,-3,6,8,1,-6,-5,4};
quickSort(array,0,array.length-1);
System.out.println(Arrays.toString(array));
}
public static void quickSort(int a[],int l,int r){
if(l>=r)
return;
int i = l; int j = r; int key = a[(l+r)/2];
// 選擇第一個數為key,我們數組中間的數為例
while(i
while(i=key)
// 從右向左找第一個小于key的值,找到了,j就前移
j--;
// 如果a[j]
if(i
a[i] = a[j];
i++;
}
while(i
// 從左向右找第一個大于key的值,找到了i就后移
i++;
// 如果a[i]>key值,a[i]會放到后面的a[j]同時j會前移
if(i
a[j] = a[i];
j--;
}
}
//i == j
a[i] = key;
quickSort(a, l, i-1);//遞歸調用
quickSort(a, i+1, r);//遞歸調用
}
}
12345678910111213141516171819202122232425262728293031323334353637383940
6.歸并排序
歸并算法的核心思想就是分解在合并,也就是分治,分解可以采用遞歸,設一個數組最右邊的元素索引為low,最左邊的元素的索引為height,中間元素索引為(low+height)/2,每一次分解可以發現當low==height的時候,整個數組被分解成每一個元素,合并就是將兩個有序歸并段歸并為一個有序的歸并段,直到有序為止
import java.util.Arrays;
public class MergeSortDemo01 {
//合并函數
public static void merge(int[] array,int low,int mid,int height){
int s1 = low;
int s2 = mid+1;
int[] ret = new int[height-low+1];
int i = 0;//表示ret數組的下標
while (s1<=mid && s2<=height){
if (array[s1]<=array[s2]){
ret[i++] = array[s1++];
}else{
ret[i++] = array[s2++];
}
}
while (s1<=mid){
ret[i++] = array[s1++];
}
while (s2<=height){
ret[i++] = array[s2++];
}
for (int j=0;j
array[low+j] = ret[j];
}
}
public static void mergeSort(int[]array,int low,int height){
if (low>=height){
return;
}
int mid = (low+height)/2;
mergeSort(array,low,mid);//遞歸分解左半部分
mergeSort(array,mid+1,height);//遞歸分解右半部本
merge(array,low,mid,height);//合并操作
}
public static void main(String[] args) {
int array[] = {10,9,2,-3,6,8,1,-6,-5,4};
System.out.println(Arrays.toString(array));
mergeSort(array,0,array.length-1);
System.out.println(Arrays.toString(array));
}
}
1234567891011121314151617181920212223242526272829303132333435363738394041424344
7.基數排序
本質上是將整數按位數切割成不同的數字,然后按每個位數分別比較,基數排序又叫桶子法
定義10個編號為0~9一維數組,找到每個數的個位數分別放在對應編號的數組中,然后再將十位數取出分別放在對應編號的數組中,直到取到最高位就變為有序
基數排序是效率最高的穩定性排序法
import java.util.Arrays;
public class RadixSortDemo01 {
public static void main(String[] args) {
int array[] = {10, 99, 2, 457, 6, 83, 16, 96, 25, 48};
radixSort(array);
}
//基數排序算法
public static void radixSort(int[] arr) {
int max = arr[0];
// 假設第一個數是最大數
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
int maxLength = (max + " ").length();
// 定義一個二維數組,表示10個桶,每一個桶是一個一維數組用于存放數據
// 為了防止放入數的時候,數據溢出,則每個一維數組的大小定位arr.length
int[][] bucket = new int[10][arr.length];
// 為了記錄每個桶中,實際存放了多少數據,我們定義一個一維數組,我們定義一個一維數組記錄各個桶每次放入的數據個數
int[] bucketCounts = new int[10];
for (int k=0,n=1;k
for (int i = 0; i < arr.length; i++) {
// 取出每個元素的個位
int digitOfElement = arr[i] / n % 10;
// 放入到對應的桶中
bucket[digitOfElement][bucketCounts[digitOfElement]] = arr[i];
// 每放一個數據此桶的中的數據就要加一
bucketCounts[digitOfElement]++;
}
// 按照這個桶的順序(一維數組的下標依次取出數據,放入原來數組)
int index = 0;
// 遍歷每一個桶并將桶中數據放入原數組
for (int i = 0; i < bucketCounts.length; i++) {
// 如果桶中有數據我們才放入到原數組
if (bucketCounts[i] != 0) {
for (int j = 0; j < bucketCounts[i]; j++) {
// 取出元素放入到arr
arr[index++] = bucket[i][j];
}
}
// 第輪處理后需要將每一個bucketCounts[i] = 0;
bucketCounts[i] = 0;
}
System.out.println("第"+(k+1)+"輪排序 arr =" + Arrays.toString(arr));
}
}
}
總結
以上是生活随笔為你收集整理的java 算法 排序算法_Java七种排序算法以及实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 多线程监听同一个端口_使用多线
- 下一篇: python具有可扩展的特性吗_1. 以