Java高頻演算法--排序、查詢總結
排序
查詢
氣泡排序
對於給定的n個記錄,從最後一個記錄開始依次對相鄰的兩個記錄進行比較,當後面的記錄小於前面的記錄時,交換位置,進行一輪比較和換位後,n個記錄中最小記錄將位於第1位;然後對後(n-1)個記錄進行第二輪比較;重複該過程直到進行比較的記錄只剩下一個為止。
public class Solution1 { //氣泡排序 public static void BubbleSort(int array[]) { int len=array.length; if(array==null||len<=0) return; for(int i=0;i<len-1;i++)//一共輪迴比較len-1次 for(int j=len-1;j>i;j--) //從後往前 if(array[j]<array[j-1]){//把最小的放在當前陣列的第一個位置 int tmp = array[j]; array[j]=array[j-1]; array[j-1]=tmp; } } public static void main(String[] args) { int []a= {3,5,2,7,3,9,1}; Solution1.BubbleSort(a); System.out.print("排序後的陣列為:"); for(int i=0;i<a.length;i++){ System.out.print(a[i]+","); } } }
快速排序
是一種非常高效的排序演算法,“分而治之”。它的基本思想是:通過一趟排序將要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料都要小,然後再按此方法對這兩部分資料分別進行快速排序,整個排序過程可以遞迴進行,以此達到整個資料變成有序序列。一趟快速排序的演算法是:
1)設定兩個變數i、j,排序開始的時候:i=0,j=N-1;
2)以第一個陣列元素作為關鍵資料,賦值給key,即key=A[0];
3)從j開始向前搜尋,即由後開始向前搜尋(j--),找到第一個小於key的值A[j],將A[j]和A[i]互換;
4)從i開始向後搜尋,即由前開始向後搜尋(i++),找到第一個大於key的A[i],將A[i]和A[j]互換;
5)重複第3、4步,直到i=j; (3,4步中,沒找到符合條件的值,即3中A[j]不小於key,4中A[i]不大於key的時候改變j、i的值,使得j=j-1,i=i+1,直至找到為止。找到符合條件的值,進行交換的時候i, j指標位置不變。另外,i==j這一過程一定正好是i+或j-完成的時候,此時令迴圈結束)
public class Solution2 { //快速排序 public static void QuickSort(int array[]){ Sort(array,0,array.length-1); } public static void Sort(int a[],int low,int high){ int i,j; if (low>=high)return; int index; i=low; j=high; index=a[i]; while(i<j){ while(i<j&&a[j]>=index) j--; if(i<j) { a[i]=a[j]; i++; } while(i<j&&a[i]<index) i++; if(i<j) { a[j]=a[i]; j--; } } a[i]=index; Sort(a,low,i-1); Sort(a,i+1,high); } public static void main(String[] args){ int a[]={3,9,2,4,8,6}; QuickSort(a); for(int i=0;i<a.length;i++){ System.out.print(a[i]+","); } } }
堆排序
是選擇排序的一種。可以利用陣列的特點快速定位指定索引的元素。堆分為大頂堆和小頂堆,是完全二叉樹。對於給定的n個記錄,初始時把這些記錄看作一棵順序儲存的二叉樹,然後將其調整為一個大頂堆,然後將堆的最後一個元素與堆頂元素交換,堆的最後一個元素即為最大記錄;接著將前(n-1)個元素(即不包括最大記錄)重新調整為一個大頂堆,再將堆頂元素與當前堆的最後一個元素進行交換得到次大的記錄;重複該過程直至調整的堆中只剩下一個元素時為止,該記錄即為最小記錄,此時可得到一個有序序列。
public class Solution3 {
//堆排序
public static void adjustMinHeap(int a[],int pos,int len){
int temp;
int child;
for(temp=a[pos];2*pos+1<=len;pos=child){
child=2*pos+1;
if(child<len&&a[child]>a[child+1])
child++;
if(a[child]<temp)
a[pos]=a[child];
else break;
}
a[pos]=temp;
}
public static void myMinHeapSort(int array[]){
int i;
int len=array.length;
for(i=len/2-1;i>=0;i--)
adjustMinHeap(array,i,len-1);
for(i=len-1;i>=0;i--){
int tmp=array[0];
array[0]=array[i];
array[i]=tmp;
adjustMinHeap(array,0,i-1);
}
}
public static void main(String[] args){
int a[]={3,9,8,4,2,1};
myMinHeapSort(a);
for(int i=0;i<a.length;i++){
System.out.print(a[i]+",");
}
}
}
插入排序
對於給定的一組記錄,初始時假設第一個記錄自成一個有序序列,其餘記錄為無序序列。接著從第二個記錄開始,按照記錄的大小依次將當前處理的記錄插入到其之前的有序序列中,直至最後一個記錄插入到有序序列中為止。
public class Solution4 {
//插入排序
public static void insertSort(int a[]){
if(a!=null){
for(int i=1;i<a.length;i++){
int temp=a[i],j=i; //a[i]表示將要進行插入操作的元素。
if(a[j-1]>temp){ //a[j-1]為前面排序好部分的最後一個元素。
while(j>=1&&a[j-1]>temp){
a[j]=a[j-1];
j--;
}
}
a[j]=temp;
}
}
}
public static void main(String[] args){
int a[]={3,9,8,4,2,1};
insertSort(a);
for(int i=0;i<a.length;i++){
System.out.print(a[i]+",");
}
}
}
選擇排序
對於給定的一組記錄,經過第一輪比較後得到最小的記錄,然後將該記錄與第一個記錄的位置進行交換;接著對不包括第一個記錄的其他記錄進行第二輪比較,得到最小的記錄並與第二個位置交換;重複該過程,直到進行比較的記錄只有一個時為止。
public class SelectSort {
public static void selectSort(int [] a){
int i,j;
int temp=0;
int flag=0;
int len=a.length;
for(i=0;i<len;i++){
temp=a[i];
flag=i;
for(j=i+1;j<len;j++){
if (a[j]<temp){
temp=a[j]; //找出最小值,賦值給temp;
flag=j; //儲存最小值的下標
}
}
if(flag!=i){ //i不是當前最小值的下標
a[flag]=a[i];
a[i]=temp; //將最小的記錄與a[i]交換。
}
}
}
public static void main(String[] args){
int a[]={3,9,2,4,8,6};
selectSort(a);
for(int i=0;i<a.length;i++){
System.out.print(a[i]+",");
}
}
}
希爾排序
是插入排序的一種。也稱縮小增量排序,是直接插入排序演算法的一種更高效的改進版本。希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序演算法排序;隨著增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個檔案恰被分成一組,演算法便終止。先取一個小於n的整數d1作為第一個增量,把檔案的全部記錄分組。所有距離為d1的倍數的記錄放在同一個組中。先在各組內進行直接插入排序;然後,取第二個增量d2<d1重複上述的分組和排序,直至所取的增量=1(< …<d2<d1),即所有記錄放在同一組中進行直接插入排序為止。
public class Shell {
public static void ShellSort(int array[]){
int len=array.length;
int i,j;
int h;
int temp;
for(h=len/2;h>0;h=h/2){
for(i=h;i<len;i++){
temp=array[i];
for(j=i-h;j>=0;j-=h){
if(temp<array[j]){
array[j+h]=array[j];
}else break;
}
array[j+h]=temp;
}
}
}
public static void main(String[] args){
int a[]={3,9,2,4,8,6};
ShellSort(a);
for(int i=0;i<a.length;i++){
System.out.print(a[i]+",");
}
}
}
歸併排序
利用遞迴和分治技術。對於給定的n個記錄,首先將每兩個相鄰的長度為1的子序列進行歸併,得到n/2(向上取整)個長度為2或1的有序子序列,再將其兩兩歸併,反覆執行此過程,直到得到一個有序序列。
import java.util.Arrays;
public class MergeSort {
public static void merge(int[] a, int low, int mid, int high) {
int[] temp = new int[high - low + 1];
int i = low; // 左指標
int j = mid + 1; // 右指標
int k = 0;
// 把較小的數先移到新陣列中
while (i <= mid && j <= high) {
if (a[i] < a[j]) {
temp[k++] = a[i++];
} else {
temp[k++] = a[j++];
}
}
// 把左邊剩餘的數移入陣列
while (i <= mid) {
temp[k++] = a[i++];
}
// 把右邊邊剩餘的數移入陣列
while (j <= high) {
temp[k++] = a[j++];
}
// 把新陣列中的數覆蓋nums陣列
for (int k2 = 0; k2 < temp.length; k2++) {
a[k2 + low] = temp[k2];
}
}
public static void mergeSort(int[] a, int low, int high) {
int mid = (low + high) / 2;
if (low < high) {
mergeSort(a, low, mid); // 左邊
mergeSort(a, mid + 1, high); // 右邊
merge(a, low, mid, high); // 左右歸併
}
}
public static void main(String[] args) {
int a[] = { 51, 46, 20, 18, 65, 97, 82, 30, 77, 50 };
mergeSort(a, 0, a.length - 1);
System.out.println("排序結果:" + Arrays.toString(a));
}
}
二分查詢
又稱折半查詢,優點是比較次數少,查詢速度快,平均效能好;其缺點是要求待查表為有序表,且插入刪除困難。因此,折半查詢方法適用於不經常變動而查詢頻繁的有序列表。二分查詢的基本思想是將n個元素分成大致相等的兩部分,取a[n/2]與x做比較,如果x=a[n/2],則找到x,演算法中止;如果x<a[n/2],則只要在陣列a的左半部分繼續搜尋x,如果x>a[n/2],則只要在陣列a的右半部搜尋x.
public class BinarySearch {
public static int sort(int []array,int index,int low,int high){
if(low<=high){
int mid=(low+high)/2;
if(index==array[mid]){
return mid; //求目標元素的下標
}
else if(index>array[mid]){
return sort(array,index,mid+1,high);
}else{
return sort(array,index,low,mid-1);
}
}
return -1;
}
public static void main(String[] args){
int a[]={1,3,4,5,6,7,8,10,34};
System.out.println(sort(a,10,0,a.length-1));
}
}
程式碼粘進程式碼框,格式有些問題,調整不了,逼死強迫症啊!啊!啊!!!