Java內(nèi)部排序之插入排序與交換排序詳解
內(nèi)部排序
排序:將任意序列重新排列按照關(guān)鍵字有序;
排序根基存儲器的不同分為:內(nèi)部排序、外部排序;(這里指的都是內(nèi)部排序)
排序根據(jù)關(guān)鍵字分為:穩(wěn)定排序、不穩(wěn)定排序
排序根據(jù)不同的原則分為:插入排序、交換排序、選擇排序、歸并排序、基數(shù)排序;
排序根據(jù)時間復(fù)雜度分為:簡單排序(O(N2))、先進排序(O(nlogn))、基數(shù)排序(O(d*n))
排序的操作:比較、移動 被稱為基于比較的排序;
假設(shè)這里使用的存儲結(jié)構(gòu)均為:順序存儲結(jié)構(gòu);
內(nèi)部排序:
1、插入排序:直接插入排序、折半插入、2-路插入排序、希爾排序
2、交換排序:冒泡排序、快速排序
3、選擇排序:簡單選擇排序、堆排序
4、歸并排序
5、基數(shù)排序
插入排序
1直接插入排序
由n-1趟排序組成; 對于P=1趟到P=N-1趟,插入排序保證從位置0到位置P上的元素為已排序狀態(tài);
第P趟,我們將位置P上的元素向左移動到它在前P+1個元素中正確位置上。(這里需要使用一個哨兵元素)
直接插入程序示例:
public class InserSort {
public static void insertSort(int a[]){
int temp;//哨兵
int i;//執(zhí)行趟數(shù)
int j;
for (i = 1; i < a.length; i++) {//執(zhí)行N-1趟
temp=a[i];
for ( j = i-1; (j >=0)&&(a[j]>temp); j--) {
a[j+1]=a[j];
}
a[j+1]=temp;
}
}
public static void main(String[] args) {
int a[]={9,6,3,2,7,5};
InserSort.insertSort(a);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]);
}
}
}算法分析:
排序的操作:比較、移動
1、空間復(fù)雜度: 只需要一個記錄的輔助空間;
2、時間復(fù)雜度:O(N2) 如果已有序時間復(fù)雜度為:O(N)
3、適應(yīng)場景:數(shù)據(jù)量不是很大 、基本有序
2 折半插入排序
將查找工作交與“折半查找”來實現(xiàn)。定位后,后續(xù)移動元素。
public class BInsertSort {
/**
* 折半插入排序
* @param a
*/
public static void BinsertSort(int a[]){
int temp;//哨兵
for (int i = 1; i < a.length; i++) {
temp=a[i];
int low=0;
int hight=i-1;
//查詢
while (low<=hight) {
int mad=(low+hight)/2;
if (a[mad]>a[i]) {
hight=mad-1;
}
if (a[mad]<a[i]) {
low=mad+1;
}
}
//移動
for (int k = i-1; k >=hight+1; k--) {
a[k+1]=a[k];
}
a[hight+1]=temp;
}
}
public static void main(String[] args) {
int a[]={9,6,3,2,7,5};
BInsertSort.BinsertSort(a);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]);
}
}
}折半插入排序減少關(guān)鍵字的比較次數(shù),但是記錄的移動次數(shù)沒有改變。
時間復(fù)雜度:O(N2)
3 希爾排序(縮小增量排序)
基本思想:先將整個待排序記錄序列分割成為若干子序列分別進行直接插入排序,待整個序列中的記錄“基本有序”時,在對整個記錄進行一次直接插入排序。
希爾排序使用一個序列,叫做增量序列。
序列最終值為1 PS:增量序列中的值沒有除1之外的公因子,并且最后一個增量必須等于1;
算法示例: 增量序列最流行的選擇是使用shell建議的序列N/2
public class ShellSort {
/**
* 希爾排序
* @param a
*/
public static void shellSort(int a[]){
int i,j;
int inc;//增量
int temp;//哨兵
for ( inc = a.length/2; inc >0; inc/=2) {//設(shè)置增量隊列
//一趟希爾排序
for ( i = inc; i < a.length; i++) {
temp=a[i];
for ( j = i; j >= inc; j-=inc) {
if (temp<a[j-inc]) {
a[j]=a[j-inc];
}else {
break;
}
}
a[j]=temp;
}
}
}
public static void main(String[] args) {
int a[]={9,6,3,2,7,5};
shellSort(a);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]);
}
}
}算法分析: 希爾排序的運算時間依賴于增量序列的選擇,最壞情況O(N2)
使用場景: 適度地大量的輸入數(shù)據(jù)
交換排序
交換排序:冒泡排序、快速排序
1 冒泡排序
思路: 一趟排序:將第一個記錄的關(guān)鍵字與第二個關(guān)鍵字進行比較,若為逆序記錄交換,然后比較第二個與第三個,以此類推,直到地N-1個記錄與N個記錄比較位置。
其結(jié)果使得最大的記錄安置在最后一個記錄位置; 第二趟對n-1個記錄進行冒泡排序。
判斷冒泡排序結(jié)束的條件:在一趟排序中沒有進行過交換記錄的操作。 算法演示:
public class BubbleSort {
/**
* 冒泡排序
* @param a
*/
public static void bubbleSort(int a[]){
int temp=0;
int log=0;//1表示有交換 0表示沒有交換 作為結(jié)束標(biāo)識
for (int i = a.length-1; i >1; i--) {
for (int j = 0; j < i; j++) {
if (a[j+1]<a[j]) {
temp=a[j+1];
a[j+1]=a[j];
a[j]=temp;
log=1;
}
}
if (log==0) {
break;
}
}
}
public static void main(String[] args) {
int a[]={2,3,5,6,7,9};
BubbleSort.bubbleSort(a);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]);
}
}
}算法分析: 時間復(fù)雜度:O(N2)
2快速排序
快速排序(Quick Sort)的基本思想:通過一趟排序?qū)⒋庞涗浄指畛瑟毩⒌膬刹糠?,其中一部分記錄的關(guān)鍵字均比另一部分記錄的關(guān)鍵字小,則可分別對這兩部分記錄繼續(xù)進行排序,以達到整個序列有序。
首先選擇一個記錄(可選擇第一個記錄,不是最佳的做法)作為支點(pivot),然后按下述原則重新排列其余記錄:將所有關(guān)鍵字較它小的記錄都安置在它的位置之前,將所有關(guān)鍵字較它大的記錄都安置在它位置之后。
由此可以該支點記錄最后所落的位置i作為分界線,這就是一趟快速排序。 具體做法:附設(shè)兩個指針low和high,它們的初值分別指向序列的前端與后端,設(shè)支點的記錄關(guān)鍵字為pivotkey,則首先從high所指位置起向前搜索找到第一個關(guān)鍵字小于pivotkey的記錄和支點記錄交換,然后從low所指位置起向后搜索,找到第一個關(guān)鍵字大于pivotkey的記錄和支點記錄相互交換,重復(fù)這兩步直到low=high為止。
算法示例:
public class QuickSort {
/**
* 一趟快排序
*/
public static int partition(int a[],int low ,int high) {
int temp = a[low];// 支點
while (low < high) {
while ((low < high)&&(a[high] >= temp) ) {
high--;
}
a[low]=a[high];
while ((low < high)&&(a[low] <= temp)) {
low++;
}
a[high]=a[low];
}
a[low]=temp;
return low;
}
/**
* 遞歸排序
* @param a
* @param low
* @param high
*/
public static void QSort(int a[],int low,int high){
//對子序列進行排序
if (low<high) {
int pivot=partition(a, low , high);
QSort(a,low, pivot-1);
QSort(a,pivot+1,high);
}
}
/**
* 快速排序
* @param a
*/
public static void QuickSort(int a[]){
QSort(a, 0, a.length-1);
}
//測試
public static void main(String[] args) {
int a[]={7,6,3,8,4,9,7};
QuickSort.QuickSort(a);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]);
}
}
}算法分析:
1、時間復(fù)雜度: 快速排序的平均時間為:O(nlogn) 就平均時間而言,快排序是目前被認(rèn)為最好的一種內(nèi)部排序方法; 較壞的情況:當(dāng)關(guān)鍵字基本有序或者有序時,快速排序?qū)⑼凶優(yōu)槊芭菖判?,時間復(fù)雜度:O(n2); 支點的選取可以優(yōu)化該算法,一般認(rèn)為“三者取中”的做法最合適:即a[i],a[j],a[(i+j)/2],取三者的中值。這樣可以改善最壞情況下的性能。
2、空間復(fù)雜度: 平均空間復(fù)雜度為:O(log2N) 因為快速排序需要一個棧空間來實現(xiàn)遞歸。 一般如果一趟排序記錄均勻分布在支點兩側(cè),棧的深度為log2N+1 最壞情況,一趟排序后,都跑到一端空間,深度為N 降低空間復(fù)雜度的方法: 在一趟排序之后比較分割所得兩部分的長度,且先對長度短的子序列中的記錄進行快速排序,則棧的最大深度可降為O(logn).
到此這篇關(guān)于Java內(nèi)部排序之插入排序與交換排序詳解的文章就介紹到這了,更多相關(guān)Java插入排序與交換排序內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解OpenFeign服務(wù)調(diào)用(微服務(wù))
OpenFeign是Spring Cloud在Feign的基礎(chǔ)上支持了SpringMVC的注解,如@RequesMapping等等,這篇文章主要介紹了OpenFeign服務(wù)調(diào)用的相關(guān)知識,需要的朋友可以參考下2022-07-07
SpringBoot分布式文件存儲數(shù)據(jù)庫mongod
MongoDB是一個基于分布式文件存儲的NoSQL數(shù)據(jù)庫,由C++語言編寫,旨在為Web應(yīng)用提供可擴展的高性能數(shù)據(jù)存儲解決方案。MongoDB是一個介于關(guān)系數(shù)據(jù)庫和非關(guān)系數(shù)據(jù)庫之間的產(chǎn)品,是非關(guān)系數(shù)據(jù)庫中功能最豐富最像關(guān)系數(shù)據(jù)庫的2023-02-02
基于Spring Boot的Environment源碼理解實現(xiàn)分散配置詳解
這篇文章主要給大家介紹了基于Spring Boot的Environment源碼理解實現(xiàn)分散配置的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08
Java案例實現(xiàn)不重復(fù)的隨機數(shù)
這篇文章主要介紹了Java案例實現(xiàn)不重復(fù)的隨機數(shù),通過創(chuàng)建Set集合對象,可以使用HashSet也可以使用TreeSet,區(qū)別在于TreeSet是排序后的,創(chuàng)建隨機數(shù)對象,獲取一個隨機數(shù)去重等操作,需要的朋友可以參考一下2022-04-04
springboot使用定時器@Scheduled不管用的解決
這篇文章主要介紹了springboot使用定時器@Scheduled不管用的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12
Feign利用自定義注解實現(xiàn)路徑轉(zhuǎn)義詳解
這篇文章主要講解一下如何通過注解實現(xiàn)對路由中的路徑進行自定義編碼,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)或工作有一定的幫助,需要的可以參考一下2022-06-06
詳解spring boot集成ehcache 2.x 用于hibernate二級緩存
本篇文章主要介紹了詳解spring boot集成ehcache 2.x 用于hibernate二級緩存,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-05-05

