首先是插入排序:
個人思路:插入排序就是將一個無序的數組,從第一個開始,將下一個數插入到前面的有序數組中,使之前的數組依然有序。(我說的比較白話,因爲是自己總結的)
比如數組 {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代碼,有些話說的太白了,可能不易於理解,請大家見諒。