導航:首頁 > 編程語言 > java常用的排序演算法

java常用的排序演算法

發布時間:2024-09-21 12:28:20

『壹』 java怎麼實現排序

Java實現幾種常見排序方法

日常操作中常見的排序方法有:冒泡排序、快速排序、選擇排序、插入排序、希爾排序,甚至還有基數排序、雞尾酒排序、桶排序、鴿巢排序、歸並排序等。
以下常見演算法的定義
1. 插入排序:插入排序基本操作就是將一個數據插入到已經排好序的有序數據中,從而得到一個新的、個數加一的有序數據,演算法適用於少量數據的排序,時間復雜度為O(n^2)。是穩定的排序方法。插入排序的基本思想是:每步將一個待排序的紀錄,按其關鍵碼值的大小插入前面已經排序的文件中適當位置上,直到全部插入完為止。
2. 選擇排序:選擇排序(Selection sort)是一種簡單直觀的排序演算法。它的工作原理是每一次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始位置,直到全部待排序的數據元素排完。 選擇排序是不穩定的排序方法。
3. 冒泡排序:冒泡排序(Bubble Sort),是一種計算機科學領域的較簡單的排序演算法。它重復地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重復地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個演算法的名字由來是因為越大的元素會經由交換慢慢「浮」到數列的頂端。
4. 快速排序:快速排序(Quicksort)是對冒泡排序的一種改進。它的基本思想是:通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然後再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。
5. 歸並排序:歸並排序是建立在歸並操作上的一種有效的排序演算法,該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合並,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合並成一個有序表,稱為二路歸並。
6. 希爾排序:希爾排序(Shell Sort)是插入排序的一種。也稱縮小增量排序,是直接插入排序演算法的一種更高效的改進版本。希爾排序是非穩定排序演算法。希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序演算法排序;隨著增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個文件恰被分成一組,演算法便終止。
https://www.cnblogs.com/wangmingshun/p/5635292.html

『貳』 常見的排序演算法—選擇,冒泡,插入,快速,歸並

太久沒看代碼了,最近打算復習一下java,又突然想到了排序演算法,就把幾種常見的排序演算法用java敲了一遍,這里統一將無序的序列從小到大排列。

選擇排序是一種簡單直觀的排序演算法。它的工作原理是:第一次從待排序的數據元素中選出最小的一個元素,存放在序列的起始位置,然後再從剩餘的未排序元素中尋找到最小元素,繼續放在下一個位置,直到待排序元素個數為0。

選擇排序代碼如下:

public void Select_sort(int[] arr) {

int temp,index;

for( int i=0;i<10;i++) {

index = i;

for(int j = i + 1 ; j < 10 ; j++) {

if(arr[j] < arr[index])

index = j;

}

/*

temp = arr[i];

arr[i] = arr[index];

arr[index] = temp;

*/

swap(arr,i,index);

}

System.out.print("經過選擇排序後:");

for(int i = 0 ; i < 10 ; i++)

System.out.print( arr[i] +" ");

System.out.println("");

}

冒泡排序是一種比較基礎的排序演算法,其思想是相鄰的元素兩兩比較,較大的元素放後面,較小的元素放前面,這樣一次循環下來,最大元素就會歸位,若數組中元素個數為n,則經過(n-1)次後,所有元素就依次從小到大排好序了。整個過程如同氣泡冒起,因此被稱作冒泡排序。

選擇排序代碼如下:

public void Bubble_sort(int[] arr) {

int temp;

for(int i = 0 ; i < 9 ; i++) {

for(int j = 0 ; j < 10 - i - 1 ;j++) {

if(arr[j] > arr[j+1]) {

/*

temp = arr[j];

arr[j] = arr[j+1];

arr[j+1] = temp;

*/

swap(arr,j,j+1);

}

}

}

System.out.print("經過冒泡排序後:");

for(int i = 0 ; i < 10 ; i++)

System.out.print( arr[i] +" ");

System.out.println("");

}

插入排序也是一種常見的排序演算法,插入排序的思想是:創建一個與待排序數組等大的數組,每次取出一個待排序數組中的元素,然後將其插入到新數組中合適的位置,使新數組中的元素保持從小到大的順序。

插入排序代碼如下:

public void Insert_sort(int[] arr) {

int length = arr.length;

int[] arr_sort = new int[length];

int count = 0;

for(int i = 0;i < length; i++) {

if(count == 0) {

arr_sort[0] = arr[0];

}else if(arr[i] >= arr_sort[count - 1]) {

arr_sort[count] = arr[i];

}else if(arr[i] < arr_sort[0]) {

insert(arr,arr_sort,arr[i],0,count);

}else {

for(int j = 0;j < count - 1; j++) {

if(arr[i] >= arr_sort[j] && arr[i] < arr_sort[j+1]) {

insert(arr,arr_sort,arr[i],j+1,count);

break;

}

}

}

count++;

}

System.out.print("經過插入排序後:");

for(int i = 0 ; i < 10 ; i++)

System.out.print( arr_sort[i] +" ");

System.out.println("");

}

public void insert(int[] arr,int[] arr_sort,int value,int index,int count) {

for(int i = count; i > index; i--)

arr_sort[i] = arr_sort[i-1];

arr_sort[index] = value;

}

快速排序的效率比冒泡排序演算法有大幅提升。因為使用冒泡排序時,一次外循環只能歸位一個值,有n個元素最多就要執行(n-1)次外循環。而使用快速排序時,一次可以將所有元素按大小分成兩堆,也就是平均情況下需要logn輪就可以完成排序。

快速排序的思想是:每趟排序時選出一個基準值(這里以首元素為基準值),然後將所有元素與該基準值比較,並按大小分成左右兩堆,然後遞歸執行該過程,直到所有元素都完成排序。

public void Quick_sort(int[] arr, int left, int right) {

if(left >= right)

return ;


int temp,t;

int j = right;

int i = left;

temp = arr[left];

while(i < j) {

while(arr[j] >= temp && i < j)

j--;

while(arr[i] <= temp && i < j)

i++;

if(i < j) {

t = arr[i];

arr[i] = arr[j];

arr[j] = t;

}

}

arr[left] = arr[i];

arr[i] = temp;


Quick_sort(arr,left, i - 1);

Quick_sort(arr, i + 1, right);

}

歸並排序是建立在歸並操作上的一種有效的排序演算法,歸並排序對序列的元素進行逐層折半分組,然後從最小分組開始比較排序,每兩個小分組合並成一個大的分組,逐層進行,最終所有的元素都是有序的。

public void Mergesort(int[] arr,int left,int right) {

if(right - left > 0) {

int[] arr_1 = new int[(right - left)/2 + 1];

int[] arr_2 = new int[(right - left + 1)/2];

int j = 0;

int k = 0;

for(int i = left;i <= right;i++) {

if(i <= (right + left)/2) {

arr_1[j++] = arr[i];

}else {

arr_2[k++] = arr[i];

}

}

Mergesort(arr_1,0,(right - left)/2);

Mergesort(arr_2,0,(right - left - 1)/2);

Merge(arr_1,arr_2,arr);

}

}

public void Merge(int[] arr_1,int[] arr_2,int[] arr) {

int i = 0;

int j = 0;

int k = 0;

int L1 = arr_1.length;

int L2 = arr_2.length;

while(i < L1 && j < L2) {

if(arr_1[i] <= arr_2[j]) {

arr[k] = arr_1[i];

i++;

}else {

arr[k] = arr_2[j];

j++;

}

k++;

}

if(i == L1) {

for(int t = j;j < L2;j++)

arr[k++] = arr_2[j];

}else {

for(int t = i;i < L1;i++)

arr[k++] = arr_1[i];

}

}

歸並排序這里我使用了left,right等變數,使其可以通用,並沒有直接用數字表示那麼明確,所以給出相關偽代碼,便於理解。

Mergesort(arr[0...n-1])

//輸入:一個可排序數組arr[0...n-1]

//輸出:非降序排列的數組arr[0...n-1]

if n>1

arr[0...n/2-1] to arr_1[0...(n+1)/2-1]//確保arr_1中元素個數>=arr_2中元素個數

//對於總個數為奇數時,arr_1比arr_2中元素多一個;對於總個數為偶數時,沒有影響

arr[n/2...n-1] to arr_2[0...n/2-1]

Mergesort(arr_1[0...(n+1)/2-1])

Mergesort(arr_2[0...n/2-1])

Merge(arr_1,arr_2,arr)

Merge(arr_1[0...p-1],arr_2[0...q-1],arr[0...p+q-1])

//輸入:兩個有序數組arr_1[0...p-1]和arr_2[0...q-1]

//輸出:將arr_1與arr_2兩數組合並到arr

int i<-0;j<-0;k<-0

while i

<p span="" do<="" j

if arr_1[i] <= arr_2[j]

arr[k] <- arr_1[i]

i<-i+1

else arr[k] <- arr_2[j];j<-j+1

k<-k+1

if i=p

arr_2[j...q-1] to arr[k...p+q-1]

else arr_1[i...p-1] to arr[k...p+q-1]

package test_1;

import java.util.Scanner;

public class Test01 {

public static void main(String[] args) {

Scanner sc = new Scanner(System.in);

int[] arr_1 = new int[10];

for(int i = 0 ; i < 10 ; i++)

arr_1[i] = sc.nextInt();

Sort demo_1 = new Sort();


//1~5一次只能運行一個,若多個同時運行,則只有第一個有效,後面幾個是無效排序。因為第一個運行的已經將帶排序數組排好序。


demo_1.Select_sort(arr_1);//-----------------------1


//demo_1.Bubble_sort(arr_1);//---------------------2


/* //---------------------3

demo_1.Quick_sort(arr_1, 0 , arr_1.length - 1);

System.out.print("經過快速排序後:");

for(int i = 0 ; i < 10 ; i++)

System.out.print( arr_1[i] +" ");

System.out.println("");

*/


//demo_1.Insert_sort(arr_1);//--------------------4


/* //--------------------5

demo_1.Mergesort(arr_1,0,arr_1.length - 1);

System.out.print("經過歸並排序後:");

for(int i = 0 ; i < 10 ; i++)

System.out.print( arr_1[i] +" ");

System.out.println("");

*/

}

}

class Sort {

public void swap(int arr[],int a, int b) {

int t;

t = arr[a];

arr[a] = arr[b];

arr[b] = t;

}


public void Select_sort(int[] arr) {

int temp,index;

for( int i=0;i<10;i++) {

index = i;

for(int j = i + 1 ; j < 10 ; j++) {

if(arr[j] < arr[index])

index = j;

}

/*

temp = arr[i];

arr[i] = arr[index];

arr[index] = temp;

*/

swap(arr,i,index);

}

System.out.print("經過選擇排序後:");

for(int i = 0 ; i < 10 ; i++)

System.out.print( arr[i] +" ");

System.out.println("");

}


public void Bubble_sort(int[] arr) {

int temp;

for(int i = 0 ; i < 9 ; i++) {

for(int j = 0 ; j < 10 - i - 1 ;j++) {

if(arr[j] > arr[j+1]) {

/*

temp = arr[j];

arr[j] = arr[j+1];

arr[j+1] = temp;

*/

swap(arr,j,j+1);

}

}

}

System.out.print("經過冒泡排序後:");

for(int i = 0 ; i < 10 ; i++)

System.out.print( arr[i] +" ");

System.out.println("");

}


public void Quick_sort(int[] arr, int left, int right) {

if(left >= right)

return ;


int temp,t;

int j = right;

int i = left;

temp = arr[left];

while(i < j) {

while(arr[j] >= temp && i < j)

j--;

while(arr[i] <= temp && i < j)

i++;

if(i < j) {

t = arr[i];

arr[i] = arr[j];

arr[j] = t;

}

}

arr[left] = arr[i];

arr[i] = temp;


Quick_sort(arr,left, i - 1);

Quick_sort(arr, i + 1, right);

}


public void Insert_sort(int[] arr) {

int length = arr.length;

int[] arr_sort = new int[length];

int count = 0;

for(int i = 0;i < length; i++) {

if(count == 0) {

arr_sort[0] = arr[0];

}else if(arr[i] >= arr_sort[count - 1]) {

arr_sort[count] = arr[i];

}else if(arr[i] < arr_sort[0]) {

insert(arr,arr_sort,arr[i],0,count);

}else {

for(int j = 0;j < count - 1; j++) {

if(arr[i] >= arr_sort[j] && arr[i] < arr_sort[j+1]) {

insert(arr,arr_sort,arr[i],j+1,count);

break;

}

}

}

count++;

}

System.out.print("經過插入排序後:");

for(int i = 0 ; i < 10 ; i++)

System.out.print( arr_sort[i] +" ");

System.out.println("");

}

public void insert(int[] arr,int[] arr_sort,int value,int index,int count) {

for(int i = count; i > index; i--)

arr_sort[i] = arr_sort[i-1];

arr_sort[index] = value;

}


public void Mergesort(int[] arr,int left,int right) {

if(right - left > 0) {

int[] arr_1 = new int[(right - left)/2 + 1];

int[] arr_2 = new int[(right - left + 1)/2];

int j = 0;

int k = 0;

for(int i = left;i <= right;i++) {

if(i <= (right + left)/2) {

arr_1[j++] = arr[i];

}else {

arr_2[k++] = arr[i];

}

}

Mergesort(arr_1,0,(right - left)/2);

Mergesort(arr_2,0,(right - left - 1)/2);

Merge(arr_1,arr_2,arr);

}

}

public void Merge(int[] arr_1,int[] arr_2,int[] arr) {

int i = 0;

int j = 0;

int k = 0;

int L1 = arr_1.length;

int L2 = arr_2.length;

while(i < L1 && j < L2) {

if(arr_1[i] <= arr_2[j]) {

arr[k] = arr_1[i];

i++;

}else {

arr[k] = arr_2[j];

j++;

}

k++;

}

if(i == L1) {

for(int t = j;j < L2;j++)

arr[k++] = arr_2[j];

}else {

for(int t = i;i < L1;i++)

arr[k++] = arr_1[i];

}

}

}

若有錯誤,麻煩指正,不勝感激。

『叄』 數據結構 java開發中常用的排序演算法有哪些

排序演算法有很多,所以在特定情景中使用哪一種演算法很重要。為了選擇合適的演算法,可以按照建議的順序考慮以下標准:
(1)執行時間
(2)存儲空間
(3)編程工作
對於數據量較小的情形,(1)(2)差別不大,主要考慮(3);而對於數據量大的,(1)為首要。

主要排序法有:
一、冒泡(Bubble)排序——相鄰交換
二、選擇排序——每次最小/大排在相應的位置
三、插入排序——將下一個插入已排好的序列中
四、殼(Shell)排序——縮小增量
五、歸並排序
六、快速排序
七、堆排序
八、拓撲排序

一、冒泡(Bubble)排序

----------------------------------Code 從小到大排序n個數------------------------------------
void BubbleSortArray()
{
for(int i=1;i<n;i++)
{
for(int j=0;i<n-i;j++)
{
if(a[j]>a[j+1])//比較交換相鄰元素
{
int temp;
temp=a[j]; a[j]=a[j+1]; a[j+1]=temp;
}
}
}
}
-------------------------------------------------Code------------------------------------------------
效率 O(n²),適用於排序小列表。

二、選擇排序
----------------------------------Code 從小到大排序n個數--------------------------------
void SelectSortArray()
{
int min_index;
for(int i=0;i<n-1;i++)
{
min_index=i;
for(int j=i+1;j<n;j++)//每次掃描選擇最小項
if(arr[j]<arr[min_index]) min_index=j;
if(min_index!=i)//找到最小項交換,即將這一項移到列表中的正確位置
{
int temp;
temp=arr[i]; arr[i]=arr[min_index]; arr[min_index]=temp;
}
}
}
-------------------------------------------------Code-----------------------------------------
效率O(n²),適用於排序小的列表。

三、插入排序
--------------------------------------------Code 從小到大排序n個數-------------------------------------
void InsertSortArray()
{
for(int i=1;i<n;i++)//循環從第二個數組元素開始,因為arr[0]作為最初已排序部分
{
int temp=arr[i];//temp標記為未排序第一個元素
int j=i-1;
while (j>=0 && arr[j]>temp)/*將temp與已排序元素從小到大比較,尋找temp應插入的位置*/
{
arr[j+1]=arr[j];
j--;
}
arr[j+1]=temp;
}
}
------------------------------Code--------------------------------------------------------------
最佳效率O(n);最糟效率O(n²)與冒泡、選擇相同,適用於排序小列表
若列表基本有序,則插入排序比冒泡、選擇更有效率。

四、殼(Shell)排序——縮小增量排序
-------------------------------------Code 從小到大排序n個數-------------------------------------
void ShellSortArray()
{
for(int incr=3;incr<0;incr--)//增量遞減,以增量3,2,1為例
{
for(int L=0;L<(n-1)/incr;L++)//重復分成的每個子列表
{
for(int i=L+incr;i<n;i+=incr)//對每個子列表應用插入排序
{
int temp=arr[i];
int j=i-incr;
while(j>=0&&arr[j]>temp)
{
arr[j+incr]=arr[j];
j-=incr;
}
arr[j+incr]=temp;
}
}
}
}
--------------------------------------Code-------------------------------------------
適用於排序小列表。
效率估計O(nlog2^n)~O(n^1.5),取決於增量值的最初大小。建議使用質數作為增量值,因為如果增量值是2的冪,則在下一個通道中會再次比較相同的元素。
殼(Shell)排序改進了插入排序,減少了比較的次數。是不穩定的排序,因為排序過程中元素可能會前後跳躍。

五、歸並排序
----------------------------------------------Code 從小到大排序---------------------------------------
void MergeSort(int low,int high)
{
if(low>=high) return;//每個子列表中剩下一個元素時停止
else int mid=(low+high)/2;/*將列表劃分成相等的兩個子列表,若有奇數個元素,則在左邊子列表大於右側子列表*/
MergeSort(low,mid);//子列表進一步劃分
MergeSort(mid+1,high);
int [] B=new int [high-low+1];//新建一個數組,用於存放歸並的元素
for(int i=low,j=mid+1,k=low;i<=mid && j<=high;k++)/*兩個子列表進行排序歸並,直到兩個子列表中的一個結束*/
{
if (arr[i]<=arr[j];)
{
B[k]=arr[i];
I++;
}
else
{ B[k]=arr[j]; j++; }
}
for( ;j<=high;j++,k++)//如果第二個子列表中仍然有元素,則追加到新列表
B[k]=arr[j];
for( ;i<=mid;i++,k++)//如果在第一個子列表中仍然有元素,則追加到新列表中
B[k]=arr[i];
for(int z=0;z<high-low+1;z++)//將排序的數組B的 所有元素復制到原始數組arr中
arr[z]=B[z];
}
-----------------------------------------------------Code---------------------------------------------------
效率O(nlogn),歸並的最佳、平均和最糟用例效率之間沒有差異。
適用於排序大列表,基於分治法。

六、快速排序
------------------------------------Code--------------------------------------------
/*快速排序的演算法思想:選定一個樞紐元素,對待排序序列進行分割,分割之後的序列一個部分小於樞紐元素,一個部分大於樞紐元素,再對這兩個分割好的子序列進行上述的過程。*/ void swap(int a,int b){int t;t =a ;a =b ;b =t ;}
int Partition(int [] arr,int low,int high)
{
int pivot=arr[low];//採用子序列的第一個元素作為樞紐元素
while (low < high)
{
//從後往前栽後半部分中尋找第一個小於樞紐元素的元素
while (low < high && arr[high] >= pivot)
{
--high;
}
//將這個比樞紐元素小的元素交換到前半部分
swap(arr[low], arr[high]);
//從前往後在前半部分中尋找第一個大於樞紐元素的元素
while (low <high &&arr [low ]<=pivot )
{
++low ;
}
swap (arr [low ],arr [high ]);//將這個樞紐元素大的元素交換到後半部分
}
return low ;//返回樞紐元素所在的位置
}
void QuickSort(int [] a,int low,int high)
{
if (low <high )
{
int n=Partition (a ,low ,high );
QuickSort (a ,low ,n );
QuickSort (a ,n +1,high );
}
}
----------------------------------------Code-------------------------------------
平均效率O(nlogn),適用於排序大列表。
此演算法的總時間取決於樞紐值的位置;選擇第一個元素作為樞紐,可能導致O(n²)的最糟用例效率。若數基本有序,效率反而最差。選項中間值作為樞紐,效率是O(nlogn)。
基於分治法。

七、堆排序
最大堆:後者任一非終端節點的關鍵字均大於或等於它的左、右孩子的關鍵字,此時位於堆頂的節點的關鍵字是整個序列中最大的。
思想:
(1)令i=l,並令temp= kl ;
(2)計算i的左孩子j=2i+1;
(3)若j<=n-1,則轉(4),否則轉(6);
(4)比較kj和kj+1,若kj+1>kj,則令j=j+1,否則j不變;
(5)比較temp和kj,若kj>temp,則令ki等於kj,並令i=j,j=2i+1,並轉(3),否則轉(6)
(6)令ki等於temp,結束。
-----------------------------------------Code---------------------------
void HeapSort(SeqIAst R)

{ //對R[1..n]進行堆排序,不妨用R[0]做暫存單元 int I; BuildHeap(R); //將R[1-n]建成初始堆for(i=n;i>1;i--) //對當前無序區R[1..i]進行堆排序,共做n-1趟。{ R[0]=R[1]; R[1]=R[i]; R[i]=R[0]; //將堆頂和堆中最後一個記錄交換 Heapify(R,1,i-1); //將R[1..i-1]重新調整為堆,僅有R[1]可能違反堆性質 } } ---------------------------------------Code--------------------------------------

堆排序的時間,主要由建立初始堆和反復重建堆這兩部分的時間開銷構成,它們均是通過調用Heapify實現的。

堆排序的最壞時間復雜度為O(nlgn)。堆排序的平均性能較接近於最壞性能。 由於建初始堆所需的比較次數較多,所以堆排序不適宜於記錄數較少的文件。 堆排序是就地排序,輔助空間為O(1), 它是不穩定的排序方法。

堆排序與直接插入排序的區別:
直接選擇排序中,為了從R[1..n]中選出關鍵字最小的記錄,必須進行n-1次比較,然後在R[2..n]中選出關鍵字最小的記錄,又需要做n-2次比較。事實上,後面的n-2次比較中,有許多比較可能在前面的n-1次比較中已經做過,但由於前一趟排序時未保留這些比較結果,所以後一趟排序時又重復執行了這些比較操作。
堆排序可通過樹形結構保存部分比較結果,可減少比較次數。

八、拓撲排序
例 :學生選修課排課先後順序
拓撲排序:把有向圖中各頂點按照它們相互之間的優先關系排列成一個線性序列的過程。
方法:
在有向圖中選一個沒有前驅的頂點且輸出
從圖中刪除該頂點和所有以它為尾的弧
重復上述兩步,直至全部頂點均已輸出(拓撲排序成功),或者當圖中不存在無前驅的頂點(圖中有迴路)為止。
---------------------------------------Code--------------------------------------
void TopologicalSort()/*輸出拓撲排序函數。若G無迴路,則輸出G的頂點的一個拓撲序列並返回OK,否則返回ERROR*/
{
int indegree[M];
int i,k,j;
char n;
int count=0;
Stack thestack;
FindInDegree(G,indegree);//對各頂點求入度indegree[0....num]
InitStack(thestack);//初始化棧
for(i=0;i<G.num;i++)
Console.WriteLine("結點"+G.vertices[i].data+"的入度為"+indegree[i]);
for(i=0;i<G.num;i++)
{
if(indegree[i]==0)
Push(thestack.vertices[i]);
}
Console.Write("拓撲排序輸出順序為:");
while(thestack.Peek()!=null)
{
Pop(thestack.Peek());
j=locatevex(G,n);
if (j==-2)
{
Console.WriteLine("發生錯誤,程序結束。");
exit();
}
Console.Write(G.vertices[j].data);
count++;
for(p=G.vertices[j].firstarc;p!=NULL;p=p.nextarc)
{
k=p.adjvex;
if (!(--indegree[k]))
Push(G.vertices[k]);
}
}
if (count<G.num)
Cosole.WriteLine("該圖有環,出現錯誤,無法排序。");
else
Console.WriteLine("排序成功。");
}
----------------------------------------Code--------------------------------------
演算法的時間復雜度O(n+e)。

『肆』 常見查找和排序演算法

查找成功最多要n 次,平均(n+1)/2次, 時間復雜度為O(n)
優點:既適用順序表也適用單鏈表,同時對表中元素順序無要求,給插入帶來方便,只需插入表尾即可。
缺點:速度較慢。

改進:在表尾設置一個崗哨,這樣不用去循環判斷數組下標是否越界,因為最後必然成立。

適用條件:

二分查找的判定樹不僅是二叉排序樹,而且是一棵理想平衡樹。 時間復雜度為O(lbn)

循環實現

遞歸實現

待排序的元素需要實現 Java 的 Comparable 介面,該介面有 compareTo() 方法,可以用它來判斷兩個元素的大小關系。

從數組中選擇最小元素,將它與數組的第一個元素交換位置。再從數組剩下的元素中選擇出最小的元素,將它與數組的第二個元素交換位置。不斷進行這樣的操作,直到將整個數組排序。

選擇排序需要 ~N2/2 次比較和 ~N 次交換,==它的運行時間與輸入無關==,這個特點使得它對一個已經排序的數組也需要這么多的比較和交換操作。

從左到右不斷 交換相鄰逆序的元素 ,在一輪的循環之後,可以讓未排序的最大元素上浮到右側。

在一輪循環中,如果沒有發生交換,那麼說明數組已經是有序的,此時可以直接退出。

每次都 將當前元素插入到左側已經排序的數組中 ,使得插入之後左側數組依然有序。

對於數組 {3, 5, 2, 4, 1},它具有以下逆序:(3, 2), (3, 1), (5, 2), (5, 4), (5, 1), (2, 1), (4, 1),插入排序每次只能交換相鄰元素,令逆序數量減少 1,因此插入排序需要交換的次數為逆序數量。

==插入排序的時間復雜度取決於數組的初始順序,如果數組已經部分有序了,那麼逆序較少,需要的交換次數也就較少,時間復雜度較低==。

對於大規模的數組,插入排序很慢,因為它只能交換相鄰的元素,每次只能將逆序數量減少 1。希爾排序的出現就是為了解決插入排序的這種局限性,它通過交換不相鄰的元素,每次可以將逆序數量減少大於 1。

希爾排序使用插入排序對間隔 h 的序列進行排序。通過不斷減小 h,最後令 h=1,就可以使得整個數組是有序的。

希爾排序的運行時間達不到平方級別,使用遞增序列 1, 4, 13, 40, ... 的希爾排序所需要的比較次數不會超過 N 的若干倍乘於遞增序列的長度。後面介紹的高級排序演算法只會比希爾排序快兩倍左右。

歸並排序的思想是將數組分成兩部分,分別進行排序,然後歸並起來。

歸並方法將數組中兩個已經排序的部分歸並成一個。

將一個大數組分成兩個小數組去求解。

因為每次都將問題對半分成兩個子問題,這種對半分的演算法復雜度一般為 O(NlogN)。

先歸並那些微型數組,然後成對歸並得到的微型數組。

取 a[l] 作為切分元素,然後從數組的左端向右掃描直到找到第一個大於等於它的元素,再從數組的右端向左掃描找到第一個小於它的元素,交換這兩個元素。不斷進行這個過程,就可以保證左指針 i 的左側元素都不大於切分元素,右指針 j 的右側元素都不小於切分元素。當兩個指針相遇時,將切分元素 a[l] 和 a[j] 交換位置。

快速排序是原地排序,不需要輔助數組,但是遞歸調用需要輔助棧。

快速排序最好的情況下是每次都正好將數組對半分,這樣遞歸調用次數才是最少的。這種情況下比較次數為 CN=2CN/2+N,復雜度為 O(NlogN)。

最壞的情況下,第一次從最小的元素切分,第二次從第二小的元素切分,如此這般。因此最壞的情況下需要比較 N2/2。為了防止數組最開始就是有序的,在進行快速排序時需要隨機打亂數組。

因為快速排序在小數組中也會遞歸調用自己,對於小數組,插入排序比快速排序的性能更好,因此在小數組中可以切換到插入排序。

最好的情況下是每次都能取數組的中位數作為切分元素,但是計算中位數的代價很高。一種折中方法是取 3 個元素,並將大小居中的元素作為切分元素。

對於有大量重復元素的數組,可以將數組切分為三部分,分別對應小於、等於和大於切分元素。

三向切分快速排序對於有大量重復元素的隨機數組可以在線性時間內完成排序。

快速排序的 partition() 方法,會返回一個整數 j 使得 a[l..j-1] 小於等於 a[j],且 a[j+1..h] 大於等於 a[j],此時 a[j] 就是數組的第 j 大元素。

可以利用這個特性找出數組的第 k 大的元素。

該演算法是線性級別的,假設每次能將數組二分,那麼比較的總次數為 (N+N/2+N/4+..),直到找到第 k 個元素,這個和顯然小於 2N。

堆中某個節點的值總是大於等於其子節點的值,並且堆是一顆完全二叉樹。

堆可以用數組來表示,這是因為堆是完全二叉樹,而完全二叉樹很容易就存儲在數組中。位置 k 的節點的父節點位置為 k/2,而它的兩個子節點的位置分別為 2k 和 2k+1。這里不使用數組索引為 0 的位置,是為了更清晰地描述節點的位置關系。

在堆中,當一個節點比父節點大,那麼需要交換這個兩個節點。交換後還可能比它新的父節點大,因此需要不斷地進行比較和交換操作,把這種操作稱為上浮。

類似地,當一個節點比子節點來得小,也需要不斷地向下進行比較和交換操作,把這種操作稱為下沉。一個節點如果有兩個子節點,應當與兩個子節點中最大那個節點進行交換。

將新元素放到數組末尾,然後上浮到合適的位置。

從數組頂端刪除最大的元素,並將數組的最後一個元素放到頂端,並讓這個元素下沉到合適的位置。

把最大元素和當前堆中數組的最後一個元素交換位置,並且不刪除它,那麼就可以得到一個從尾到頭的遞減序列,從正向來看就是一個遞增序列,這就是堆排序。

一個堆的高度為logN,因此在堆中插入元素和刪除最大元素的復雜度都為 logN。

對於堆排序,由於要對 N 個節點進行下沉操作,因此復雜度為 NlogN。

堆排序是一種原地排序,沒有利用額外的空間。

現代操作系統很少使用堆排序,因為它無法利用局部性原理進行緩存,也就是數組元素很少和相鄰的元素進行比較和交換。

計數排序的核心在於將輸入的數據值轉化為鍵存儲在額外開辟的數組空間中。作為一種線性時間復雜度的排序,==計數排序要求輸入的數據必須是有確定范圍的整數==。

當輸入的元素是 n 個 0 到 k 之間的整數時,它的==運行時間是 O(n + k)==。計數排序不是比較排序,排序的速度快於任何比較排序演算法。由於用來計數的數組C的長度取決於待排序數組中數據的范圍(等於待排序數組的最大值與最小值的差加上1),這使得計數排序對於數據范圍很大的數組,需要大量時間和內存。比較適合用來排序==小范圍非負整數數組的數組==。

桶排序是計數排序的升級版。它利用了函數的映射關系,高效與否的關鍵就在於這個映射函數的確定。為了使桶排序更加高效,我們需要做到這兩點:

同時,對於桶中元素的排序,選擇何種比較排序演算法對於性能的影響至關重要。

當輸入數據均勻分配到每一個桶時最快,當都分配到同一個桶時最慢。

實間復雜度N*K

快速排序是最快的通用排序演算法,它的內循環的指令很少,而且它還能利用緩存,因為它總是順序地訪問數據。它的運行時間近似為 ~cNlogN,這里的 c 比其它線性對數級別的排序演算法都要小。

使用三向切分快速排序,實際應用中可能出現的某些分布的輸入能夠達到線性級別,而其它排序演算法仍然需要線性對數時間。

『伍』 Java通過幾種經典的演算法來實現數組排序

JAVA中在運用數組進行排序功能時,一般有四種方法:快速排序法、冒泡法、選擇排序法、插入排序法。
快速排序法主要是運用了Arrays中的一個方法Arrays.sort()實現。
冒泡法是運用遍歷數組進行比較,通過不斷的比較將最小值或者最大值一個一個的遍歷出來。
選擇排序法是將數組的第一個數據作為最大或者最小的值,然後通過比較循環,輸出有序的數組。
插入排序是選擇一個數組中的數據,通過不斷的插入比較最後進行排序。下面我就將他們的實現方法一一詳解供大家參考。
<1>利用Arrays帶有的排序方法快速排序

public class Test2{ public static void main(String[] args){ int[] a={5,4,2,4,9,1}; Arrays.sort(a); //進行排序 for(int i: a){ System.out.print(i); } } }

<2>冒泡排序演算法

public static int[] bubbleSort(int[] args){//冒泡排序演算法 for(int i=0;i<args.length-1;i++){ for(int j=i+1;j<args.length;j++){ if (args[i]>args[j]){ int temp=args[i]; args[i]=args[j]; args[j]=temp; } } } return args; }

<3>選擇排序演算法

public static int[] selectSort(int[] args){//選擇排序演算法 for (int i=0;i<args.length-1 ;i++ ){ int min=i; for (int j=i+1;j<args.length ;j++ ){ if (args[min]>args[j]){ min=j; } } if (min!=i){ int temp=args[i]; args[i]=args[min]; args[min]=temp; } } return args; }

<4>插入排序演算法

public static int[] insertSort(int[] args){//插入排序演算法 for(int i=1;i<args.length;i++){ for(int j=i;j>0;j--){ if (args[j]<args[j-1]){ int temp=args[j-1]; args[j-1]=args[j]; args[j]=temp; }else break; } } return args; }

『陸』 java排列組合的演算法 譬如我有(A,B,C,D),我想輸出的結果是

我覺得可以看成數字的排列如 1 2 3 4分別代表A B C D
就是將1 2 3 4排列
四位的就是1234
三位的就是從這四個數字中取出三個數字,得到的三位數是最小的,如:
取 1 2 3 可以得到123 213 321 132等等 其中123是最小的
兩為數字的跟三位數字的一樣

『柒』 java十大演算法

演算法一:快速排序演算法
快速排序是由東尼·霍爾所發展的一種排序演算法。在平均狀況下,排序 n 個項目要Ο(n log n)次比較。在最壞狀況下則需要Ο(n2)次比較,但這種狀況並不常見。事實上,快速排序通常明顯比其他Ο(n log n) 演算法更快,因為它的內部循環(inner loop)可以在大部分的架構上很有效率地被實現出來。

快速排序使用分治法(Divide and conquer)策略來把一個串列(list)分為兩個子串列(sub-lists)。

演算法步驟:

1 從數列中挑出一個元素,稱為 "基準"(pivot),

2 重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分區退出之後,該基準就處於數列的中間位置。這個稱為分區(partition)操作。

3 遞歸地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。

遞歸的最底部情形,是數列的大小是零或一,也就是永遠都已經被排序好了。雖然一直遞歸下去,但是這個演算法總會退出,因為在每次的迭代(iteration)中,它至少會把一個元素擺到它最後的位置去。

演算法二:堆排序演算法
堆排序(Heapsort)是指利用堆這種數據結構所設計的一種排序演算法。堆積是一個近似完全二叉樹的結構,並同時滿足堆積的性質:即子結點的鍵值或索引總是小於(或者大於)它的父節點。

堆排序的平均時間復雜度為Ο(nlogn) 。

演算法步驟:

創建一個堆H[0..n-1]

把堆首(最大值)和堆尾互換

3. 把堆的尺寸縮小1,並調用shift_down(0),目的是把新的數組頂端數據調整到相應位置

4. 重復步驟2,直到堆的尺寸為1

演算法三:歸並排序
歸並排序(Merge sort,台灣譯作:合並排序)是建立在歸並操作上的一種有效的排序演算法。該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。

演算法步驟:

1. 申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合並後的序列

2. 設定兩個指針,最初位置分別為兩個已經排序序列的起始位置

3. 比較兩個指針所指向的元素,選擇相對小的元素放入到合並空間,並移動指針到下一位置

4. 重復步驟3直到某一指針達到序列尾

5. 將另一序列剩下的所有元素

『捌』 java實現幾種常見排序演算法

下面給你介紹四種常用排序演算法:

1、冒泡排序

特點:效率低,實現簡單

思想(從小到大排):每一趟將待排序序列中最大元素移到最後,剩下的為新的待排序序列,重復上述步驟直到排完所有元素。這只是冒泡排序的一種,當然也可以從後往前排。

閱讀全文

與java常用的排序演算法相關的資料

熱點內容
半夜解壓有什麼壞處 瀏覽:424
linux代理命令 瀏覽:637
調用tasking的編譯器編譯 瀏覽:292
青檸app是什麼 瀏覽:866
linuxapachephp56 瀏覽:395
安卓手機如何打開eng文件 瀏覽:22
看拉丁電視都用什麼app好 瀏覽:778
什麼是哲學pdf 瀏覽:509
hdfs的三個下載命令 瀏覽:524
java常用的排序演算法 瀏覽:358
51單片機連接adc 瀏覽:859
python命名變數報錯 瀏覽:120
安卓手機如何換windows系統 瀏覽:612
python中的類是什麼 瀏覽:631
我的英雄學院用哪個app可以看 瀏覽:36
excel插入選項卡對象命令 瀏覽:695
python字元全排列 瀏覽:507
824頁大瓜文件pdf 瀏覽:222
朔州ios源碼 瀏覽:251
演算法邏輯電路 瀏覽:943