用Java實現 一些面試要求的基本的排序算法

首先是插入排序:

個人思路:插入排序就是將一個無序的數組,從第一個開始,將下一個數插入到前面的有序數組中,使之前的數組依然有序。(我說的比較白話,因爲是自己總結的)

比如數組 {1,5,3,4,5,8,2},從第二個開始,跟前面的數比較,如果小於前面的數,則交換。所以步驟如下:

{1,5,3,4,5,8,2}-->{1,3,5,4,5,8,2}-->{1,3,4,5,8,2}-->{1,3,4,5,8,2}-->{1,3,4,5,2,8}-->{1,3,4,2,5,8}-->{1,3,2,4,5,8}-->{1,2,3,4,5,8},最後排序完成。

時間複雜度:平均情況下爲O(nlogn) 最壞情況下爲O(n^2)

算法實現爲:

public class InsertSort {
	public static void main(String []args){
		int a[] = {1,5,3,4,5,8,10,21,4,5,1};
		insertSort(a);
		for(int i =0;i<a.length;i++){
			System.out.print(a[i]+"   ");
		}
	}
	public static void insertSort(int []a){
		//從第二位開始
		for(int i=1;i<a.length;i++){
			//判斷j是否大於零,這樣避免a[j-1]越界
			//從i開始,依次找前面的數,如果a[j]<a[j-1](後面的數大於前面的數),
			//則做交換,並且j--。 如果a[j]>a[j-1],則說明已經到了正確的位置,結束for循環
			for(int j=i;j>0&&(a[j]<a[j-1]);j--){
				int temp = a[j];
				a[j] = a[j-1];
				a[j-1] = temp;
			}
		}
	}
}


希爾排序:希爾排序是先取一個小於n的整數d1作爲第一個增量,把文件的全部記錄分成d1個組。所有距離爲dl的倍數的記錄放在同一個組中。先在各組內進行直接插入排序;然後,取第二個增量d2<d1重複上述的分組和排序,直至所取的增量dt=1(dt<dt-l<;…<d2<d1),即所有記錄放在同一組中進行直接插入排序爲止。

該方法實質上是一種分組插入方法。算法實現如下:

public class ShellSort {
	public static void main(String[] args) {
		int a[] = {1,5,3,4,5,8,10,21,4,5,1};
		shellSort(a);
		for(int i =0;i<a.length;i++){
			System.out.print(a[i]+"   ");
		}
	}
	public static void shellSort(int a[]){
		//i是增量的值
		for(int i=a.length/2;i>2;i/=2){
			//將前i個屬於總量爲i的不同分組做插入排序
			for(int j=0;j<i;j++){
				insertSort(a,j,i);
			}
		}
		insertSort(a,0,1);
	}
	public static void insertSort(int a[],int start,int inc){
		//從start開始沒意義,所以從第二個屬於inc增量的組的開始算
		for(int i=start+inc;i<a.length;i+=inc){
			//用插入排序對其進行排序  當j>=inc時,是因爲最小j就爲inc,如果比inc還小,則會越界
			for(int j=i;j>=inc&&(a[j]<a[j-inc]);j-=inc){
				int temp = a[j];
				a[j] = a[j-inc];
				a[j-inc] = temp;
			}
		}
	}
}

堆排序: 堆排序是用數組來表示一個完全二叉樹。 具體思路就不寫了,在算法代碼中我直接用註釋說明,原理大家找下資料就可以了

時間複雜度:最好 最壞 平均 都爲  O(nlogn)

public class HeapSort {
	//本人用的是大根堆
	public static void main(String[] args) {
		int a[] = {1,5,3,4,5,8,10,21,4,50,100,5,1};
		heapSort(a);
		for(int i =0;i<a.length;i++){
			System.out.print(a[i]+"   ");
		}
	}
	//moveDown主要是用來將子樹初始化,first相當於當前子樹的根,last是最後一個節點的位置
	public static void moveDown(int a[],int first,int last){
		//得到左子樹   因爲數組是從零開始,所以需要加一
		int largest = 2*first+1;
		while(largest<=last){//largest可以等於largest因爲最後一位也可能是最大值,不能去除
			//這個循環是爲了找到最大節點的位置
			//largest記錄着當前最大節點的位置
			while(largest<last&&(a[largest]<a[largest+1])) largest++;
			//找到最大的位置,判斷是否比first處的值大,大的話,交換值,同時因爲移動了子樹的節點
			//largest爲根的子樹的堆混亂了,需要重新建堆,所以將根first設爲largest
			//largest依舊取根的左子樹
			//如果小的話,則說明根處的值已經是最大的了,跳出循環
			if(a[first]<a[largest]){
				int temp = a[first];
				a[first] = a[largest];
				a[largest] = temp;
				first = largest;
				largest = 2*first+1;
			}else{
				largest = last+1;
			}
		}
	}
	public static void heapSort(int a[]){
		//i=a.length/2-1,得到最後一個葉子節點的父親,從最後的一個子樹開始進行建堆
		for(int i=a.length/2-1;i>=0;i--){
			moveDown(a,i,a.length-1);
		}
		//從最後一個開始,依次將最大的數交換到最後,
		for(int i=a.length-1;i>0;i--){
			int temp = a[0];
			a[0] = a[i];
			a[i] = temp;
			//然後在將堆重新構造
			moveDown(a,0,i-1);
		}
	}
}




冒泡排序:最基本的排序,基本上大家都會0 0,就是依次選第i位(i<n),並從後面開始,將i後的最小的數冒到第i位。

算法實現:

public class maopao {
	public static void main(String []args){
		int a[] = {1,5,3,4,5,8,10,21,4,5,1};
		mao(a);
		for(int i =0;i<a.length;i++){
			System.out.print(a[i]+"   ");
		}
	}
	public static void mao(int a[]){
		//i從0開始
		for(int i=0;i<a.length;i++){
			//從最後一位開始,如果小於前面的數,則交換
			for(int j=a.length-1;j>i;j--){
				if(a[j]<a[j-1]){
					int temp = a[j];
					a[j] = a[j-1];
					a[j-1] = temp;
				}
			}
		}
	}
}

選擇排序:

數組從i(0<i<n)開始,需要一個輔助數據,temp,存儲i之後的最小的數的位置,如果選擇之後,temp!=i,則交換temp和i的數,i++;

算法如下:

public class SelectSort {
	public static void main(String []args){
		int a[] = {1,5,3,4,5,8,10,21,4,5,1};
		selectSort(a);
		for(int i =0;i<a.length;i++){
			System.out.print(a[i]+"   ");
		}
	}
	public static void selectSort(int a[]){
		//存儲當前最小的數的位置
		int temp;
		for(int i=0;i<a.length;i++){
			//temp剛開始爲i
			temp = i;
			for(int j=i+1;j<a.length;j++){
				//如果存在比他小的數,則temp=j
				if(a[temp]>a[j]){
					temp = j;
				}
			}
			//如果temp!=i,說明後面有比i位上的數更小的數
			//交換temp和i位的數
			if(temp!=i){
				int t = a[i];
				a[i] = a[temp];
				a[temp] = t;
			}
		}
	}
}


快排: 設要排序的數組是A[0]……A[N-1],首先任意選取一個數據(通常選用數組的第一個數)作爲關鍵數據,然後將所有比它小的數都放到它前面,所有比它大的數都放到它後面,這個過程稱爲一趟快速排序。值得注意的是,快速排序不是一種穩定的排序算法,也就是說,多個相同的值的相對位置也許會在算法結束時產生變動。

算法如下:

public class quickSort {
	public static void main(String[] args) {
		int a[] = {1,5,3,4,5,8,10,21,4,5,1};
		quickSort(a,0,a.length-1);
		for(int i =0;i<a.length;i++){
			System.out.print(a[i]+"   ");
		}
	}
	//得到中間位置,這個位置的前面的數都小於他,後面的數都大於他
	public static int partition(int a[],int low,int high){
		//以low處爲基準點
		int paior = a[low];
		while(low<high){
			//從後看,如果high大於等於基準點,則high--
			while(low<high&&a[high]>=paior) high--;
			//這個時候high處的值小於等於基準點,將值付給low
			a[low] = a[high];
			//從前面看,如果low小於基準點的值,則low++
			while(low<high&&a[low]<=paior) low++;
			//這個時候low處的值大於等於基準點,將值付給high
			a[high] = a[low];
		}
		//最後將low處附上基準點的值,low就是基準點的位置,返回low
		a[low] = paior;
		return low;
	}
	public static void quickSort(int a[],int low,int high){
		if(low<high){
			//找到基準點
			int part = partition(a, low, high);
			//將基準點前面的數在做排序
			quickSort(a, low, part-1);
			//將基準點後面的數在做排序
			quickSort(a, part+1,high);
		}
	}
}

歸併排序:歸併(Merge)排序法是將兩個(或兩個以上)有序表合併成一個新的有序表,即把待排序序列分爲若干個有序的子序列,再把有序的子序列合併爲整體有序序列。

算法如下:

public class MergeSort {
	public static void main(String[] args) {
		int a[] = {1,5,3,4,5,8,10,21,4,5,1};
		int b[] = new int[a.length];
		mergeSort(a,b,0,a.length-1);
		for(int i =0;i<b.length;i++){
			System.out.print(b[i]+"   ");
		}
	}
	//合併 a的low到mid的有序數組,和mid到high的有序數組,合併成b
	public static void merge(int a[],int b[],int low,int mid,int high){
		int i = low,j=mid+1,k=low;
		while(i<=mid&&j<=high){
			if(a[i]<a[j]) b[k++] = a[i++];
			else b[k++] = a[j++];
		}
		while(i<=mid){
			b[k++] = a[i++];
		}
		while(j<=high){
			b[k++] = a[j++];
		}
	}
	public static void mergeSort(int a[],int b[],int low,int high){
		//s是中間數組
		int s[] = new int[a.length];
		if(low==high) b[low] = a[low];
		else{
			int mid = (low+high)/2;
			mergeSort(a,s,low,mid);
			mergeSort(a,s,mid+1,high);
			merge(s,b,low,mid,high);
		}
	}

}


本文章是我這兩天看過總結的java代碼,有些話說的太白了,可能不易於理解,請大家見諒。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章