本文目錄一覽:
請給出java幾種排序方法
java常見的排序分為:
1 插入類排序
主要就是對於一個已經有序的序列中,插入一個新的記錄。它包括:直接插入排序,折半插入排序和希爾排序
2 交換類排序
這類排序的核心就是每次比較都要“交換”,在每一趟排序都會兩兩發生一系列的“交換”排序,但是每一趟排序都會讓一個記錄排序到它的最終位置上。它包括:起泡排序,快速排序
3 選擇類排序
每一趟排序都從一系列數據中選擇一個最大或最小的記錄,將它放置到第一個或最後一個為位置交換,只有在選擇後才交換,比起交換類排序,減少了交換記錄的時間。屬於它的排序:簡單選擇排序,堆排序
4 歸併類排序
將兩個或兩個以上的有序序列合併成一個新的序列
5 基數排序
主要基於多個關鍵字排序的。
下面針對上面所述的算法,講解一些常用的java代碼寫的算法
二 插入類排序之直接插入排序
直接插入排序,一般對於已經有序的隊列排序效果好。
基本思想:每趟將一個待排序的關鍵字按照大小插入到已經排序好的位置上。
算法思路,從後往前先找到要插入的位置,如果小於則就交換,將元素向後移動,將要插入數據插入該位置即可。時間複雜度為O(n2),空間複雜度為O(1)
package sort.algorithm;
public class DirectInsertSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int data[] = { 2, 6, 10, 3, 9, 80, 1, 16, 27, 20 };
int temp, j;
for (int i = 1; i data.length; i++) {
temp = data[i];
j = i – 1;
// 每次比較都是對於已經有序的
while (j = 0 data[j] temp) {
data[j + 1] = data[j];
j–;
}
data[j + 1] = temp;
}
// 輸出排序好的數據
for (int k = 0; k data.length; k++) {
System.out.print(data[k] + ” “);
}
}
}
三 插入類排序之折半插入排序(二分法排序)
條件:在一個已經有序的隊列中,插入一個新的元素
折半插入排序記錄的比較次數與初始序列無關
思想:折半插入就是首先將隊列中取最小位置low和最大位置high,然後算出中間位置mid
將中間位置mid與待插入的數據data進行比較,
如果mid大於data,則就表示插入的數據在mid的左邊,high=mid-1;
如果mid小於data,則就表示插入的數據在mid的右邊,low=mid+1
最後整體進行右移操作。
時間複雜度O(n2),空間複雜度O(1)
package sort.algorithm;
//折半插入排序
public class HalfInsertSort {
public static void main(String[] args) {
int data[] = { 2, 6, 10, 3, 9, 80, 1, 16, 27, 20 };
// 存放臨時要插入的元素數據
int temp;
int low, mid, high;
for (int i = 1; i data.length; i++) {
temp = data[i];
// 在待插入排序的序號之前進行折半插入
low = 0;
high = i – 1;
while (low = high) {
mid = (low + high) / 2;
if (temp data[mid])
high = mid – 1;
else
// low=high的時候也就是找到了要插入的位置,
// 此時進入循環中,將low加1,則就是要插入的位置了
low = mid + 1;
}
// 找到了要插入的位置,從該位置一直到插入數據的位置之間數據向後移動
for (int j = i; j = low + 1; j–)
data[j] = data[j – 1];
// low已經代表了要插入的位置了
data[low] = temp;
}
for (int k = 0; k data.length; k++) {
System.out.print(data[k] + ” “);
}
}
}
四 插入類排序之希爾排序
希爾排序,也叫縮小增量排序,目的就是儘可能的減少交換次數,每一個組內最後都是有序的。
將待續按照某一種規則分為幾個子序列,不斷縮小規則,最後用一個直接插入排序合成
空間複雜度為O(1),時間複雜度為O(nlog2n)
算法先將要排序的一組數按某個增量d(n/2,n為要排序數的個數)分成若干組,每組中記錄的下標相差d.對每組中全部元素進行直接插入排序,然後再用一個較小的增量(d/2)對它進行分組,在每組中再進行直接插入排序。當增量減到1時,進行直接插入排序後,排序完成。
package sort.algorithm;
public class ShellSort {
public static void main(String[] args) {
int a[] = { 1, 54, 6, 3, 78, 34, 12, 45, 56, 100 };
double d1 = a.length;
int temp = 0;
while (true)
{
//利用這個在將組內倍數減小
//這裡依次為5,3,2,1
d1 = Math.ceil(d1 / 2);
//d為增量每個分組之間索引的增量
int d = (int) d1;
//每個分組內部排序
for (int x = 0; x d; x++)
{
//組內利用直接插入排序
for (int i = x + d; i a.length; i += d) {
int j = i – d;
temp = a[i];
for (; j = 0 temp a[j]; j -= d) {
a[j + d] = a[j];
}
a[j + d] = temp;
}
}
if (d == 1)
break;
}
for (int i = 0; i a.length; i++)
System.out.print(a[i]+” “);
}
}
五 交換類排序之冒泡排序
交換類排序核心就是每次比較都要進行交換
冒泡排序:是一種交換排序
每一趟比較相鄰的元素,較若大小不同則就會發生交換,每一趟排序都能將一個元素放到它最終的位置!每一趟就進行比較。
時間複雜度O(n2),空間複雜度O(1)
package sort.algorithm;
//冒泡排序:是一種交換排序
public class BubbleSort {
// 按照遞增順序排序
public static void main(String[] args) {
// TODO Auto-generated method stub
int data[] = { 2, 6, 10, 3, 9, 80, 1, 16, 27, 20, 13, 100, 37, 16 };
int temp = 0;
// 排序的比較趟數,每一趟都會將剩餘最大數放在最後面
for (int i = 0; i data.length – 1; i++) {
// 每一趟從開始進行比較,將該元素與其餘的元素進行比較
for (int j = 0; j data.length – 1; j++) {
if (data[j] data[j + 1]) {
temp = data[j];
data[j] = data[j + 1];
data[j + 1] = temp;
}
}
}
for (int i = 0; i data.length; i++)
System.out.print(data[i] + ” “);
}
}
數據結構 java開發中常用的排序算法有哪些
排序算法有很多,所以在特定情景中使用哪一種算法很重要。為了選擇合適的算法,可以按照建議的順序考慮以下標準:
(1)執行時間
(2)存儲空間
(3)編程工作
對於數據量較小的情形,(1)(2)差別不大,主要考慮(3);而對於數據量大的,(1)為首要。
主要排序法有:
一、冒泡(Bubble)排序——相鄰交換
二、選擇排序——每次最小/大排在相應的位置
三、插入排序——將下一個插入已排好的序列中
四、殼(Shell)排序——縮小增量
五、歸併排序
六、快速排序
七、堆排序
八、拓撲排序
一、冒泡(Bubble)排序
———————————-Code 從小到大排序n個數————————————
void BubbleSortArray()
{
for(int i=1;in;i++)
{
for(int j=0;in-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;in-1;i++)
{
min_index=i;
for(int j=i+1;jn;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;in;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;incr0;incr–)//增量遞減,以增量3,2,1為例
{
for(int L=0;L(n-1)/incr;L++)//重複分成的每個子列表
{
for(int i=L+incr;in;i+=incr)//對每個子列表應用插入排序
{
int temp=arr[i];
int j=i-incr;
while(j=0arr[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;zhigh-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+1kj,則令j=j+1,否則j不變;
(5)比較temp和kj,若kjtemp,則令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;i1;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;iG.num;i++)
Console.WriteLine(“結點”+G.vertices[i].data+”的入度為”+indegree[i]);
for(i=0;iG.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 (countG.num)
Cosole.WriteLine(“該圖有環,出現錯誤,無法排序。”);
else
Console.WriteLine(“排序成功。”);
}
—————————————-Code————————————–
算法的時間複雜度O(n+e)。
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實現快速排序算法?
本人特地給你編的代碼\x0d\x0a親測\x0d\x0a\x0d\x0apublicclassQuickSort{\x0d\x0a\x0d\x0apublicstaticintPartition(inta[],intp,intr){\x0d\x0aintx=a[r-1];\x0d\x0ainti=p-1;\x0d\x0ainttemp;\x0d\x0afor(intj=p;jif(a[j-1]//swap(a[j-1],a[i-1]);\x0d\x0ai++;\x0d\x0atemp=a[j-1];\x0d\x0aa[j-1]=a[i-1];\x0d\x0aa[i-1]=temp;\x0d\x0a\x0d\x0a}\x0d\x0a}\x0d\x0a//swap(a[r-1,a[i+1-1]);\x0d\x0atemp=a[r-1];\x0d\x0aa[r-1]=a[i+1-1];\x0d\x0aa[i+1-1]=temp;\x0d\x0a\x0d\x0areturni+1;\x0d\x0a\x0d\x0a}\x0d\x0a\x0d\x0apublicstaticvoidQuickSort(inta[],intp,intr){\x0d\x0a\x0d\x0aif(p
Java的排序算法有哪些
java的排序大的分類可以分為兩種:內排序和外排序。在排序過程中,全部記錄存放在內存,則稱為內排序,如果排序過程中需要使用外存,則稱為外排序。下面講的排序都是屬於內排序。
1.插入排序:直接插入排序、二分法插入排序、希爾排序。
2.選擇排序:簡單選擇排序、堆排序。
3.交換排序:冒泡排序、快速排序。
4.歸併排序
5.基數排序
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/288665.html