目錄
 一、文字
1.排序的概念及其運用
1.1排序的概念
1.2排序運用
1.3常見的排序演算法
2 .插入排序演算法的實現
2.1插入排序
二、测试代码
首頁 Java java教程 Java資料結構之插入排序與希爾排序怎麼實現

Java資料結構之插入排序與希爾排序怎麼實現

May 13, 2023 pm 03:19 PM
java

     一、文字

    1.排序的概念及其運用

    1.1排序的概念

    排序:所謂排序,就是使一串記錄,按照其中的某個或某些關鍵字的大小,遞增或遞減的排列起來的操作

    穩定性:假定在待排序的記錄序列中,存在多個具有相同的關鍵字的記錄,若經過排序,這些記錄的相對次序保持不變,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序後的序列中,r[i]仍在r[j]之前,則稱這種排序演算法是穩定的;否則稱為不穩定的。

    內部排序:資料元素全部放在記憶體中的排序。

    外部排序:資料元素太多不能同時放在記憶體中,根據排序過程的要求不能在內外記憶體之間移動資料的排序。

    1.2排序運用

            看過排序的基礎概念,可能有的小夥伴會問就算我學會了排序,但是在實際生活中有什麼用嗎?其實排序在生活中無所不在,比如說對一件商品不同維度的選擇,又或者是對高校的排名,其實背後都存在著排序的思想,學好排序,能夠幫助我們以另一個維度來觀察生活中的方方面面並幫助我們更好地解決生活中的問題

    Java資料結構之插入排序與希爾排序怎麼實現

    Java資料結構之插入排序與希爾排序怎麼實現

    1.3常見的排序演算法

    在資料結構這一塊,我們常見的排序演算法共有四種:

    插入排序:直接插入排序、希爾排序

    選擇排序:選擇排序、堆排序

    交換排序:冒泡排序、快速排序

    歸併排序:歸併排序

    2 .插入排序演算法的實現

            由於篇幅的關係,本篇我們主要介紹的是插入排序中的直接插入排序希爾排序 ,而直接插入排序又常被稱為插入排序。

    2.1插入排序

    2.1.1基本想法

            直接插入排序法是簡單的插入排序法

    #     直接插入排序法是一種簡單的插入排序法#     基本想法是

    把待排序的記錄按其關鍵碼值的大小逐一插入到一個已經排好序的有序序列中,直到所有的記錄插入完為止,得到一個新的有序序列

            實際上我們在玩撲克牌時,就用了插入排序的想法。當

    你摸了一張新牌,自然而然地就會與手上已有的牌堆進行一一比較,在比較之後將其放入其應該所處的位置
    。所以我們可能不知道插入排序是什麼,但我們潛意識的做法恰恰就符合了插入排序。

     2.1.2直接插入排序

            以較書面的語言描述直接插入排序:當插入第i(i>=1)個元素時,前面的array[0],array[1],…,array[i-1]已經排好序,此時用array[i]的排序碼與array[i-1],array[i-2], …的排序碼順序進行比較,找到插入位置即將array[i]插入,原來位置上的元素順序後移        但這麼說可能有的小伙伴會不太理解,那麼通俗地來講吧。現在

    在你面前有一個亂序的數組,我們的目的是要將這個亂序的數組調整為升序或是降序

            以升序為例meth,由於陣列是無序的,因此我們需要

    從陣列的第二個元素開始排序###。為什麼不是第一個呢,因為只有一個數字的時候,你無法與其餘元素比較,自然也就沒有亂序一說,因此只有一個元素的時候我們就默認它是有序的。 ###

            在理解為什麼要從第二個元素開始排序後,現在我們就要進行元素的依序插入和排序了。先是第二個元素的插入和排序,在下圖中我們會發現第二個元素是44,44大於第一個元素3,因此不需要挪動第二個元素。緊接著就是第三個元素的插入和排序,我們發現第三個元素38小於第二個元素44,不符合我們升序的預期,因此將44挪動到38的位置,在第二、三個元素有序後,我們發現38大於3,也就是第一、二個元素也是有序的,因此就無需再挪動第一個元素的位置,這時候我們已經確認38應該所處的是數組中第二個元素的位置,因此我們只需將38插入到第二個元素的位置即可。相信看到這裡的小夥伴對後續元素的插入與排序應該是信手拈來了,

            接下來就是代碼的書寫了。在程式碼上,我們該如何實現上述元素的插入與排序呢?我們採取了兩個主要的變數「des」「end」,des就是我們所要插入的元素的初識下標,而end代表的是插入之前的序列的最後一個元素的下標,隨著des的比較,end要不斷向前移動,那麼什麼時候end的移動才會停止呢,也就是比較的結束,大致分為兩種情況 :①des所代表的元素大於end所代表的的元素 ②end已經來到序列的第一個元素,這時候des要不是第一個元素,或是第二個元素。

            特定圖片與程式碼如下:

    Java資料結構之插入排序與希爾排序怎麼實現

    Java資料結構之插入排序與希爾排序怎麼實現

    //插入排序[升序]
    int* InsertSort(int* arr, int n)
    {
     
    	//整体排序
    	for (int i = 1; i < n; i++)
    	{
    		int end = i - 1;
    		int des = arr[i];
    		//单趟排序
    		while (end >= 0)
    		{
    			if (des >= arr[end])
    				break;
    			if (des < arr[end])
    			{
    				arr[end + 1] = arr[end];
    				end--;
    			}
    			arr[end+1] = des;
    		}
    	}
    }
    登入後複製

    # 附註:直接插入排序特性總結

    ①元素集合越接近有序,直接插入排序演算法的時間效率越高

    ②時間複雜度:O(N^2)

    ③ 空間複雜度:O(1),它是一種穩定的排序演算法

    ④ 穩定性:穩定

    2.1.3希爾排序(縮小增量排序)

            希爾排序法又稱為縮小增量法。

            希爾排序法的基本想法是:先選定一個整數,把待排序文件中所有記錄分成整數組,所有距離為的記錄分在同一組內,並對每一組內的記錄進行排序。然後重複上述分組和排序的工作,當到達整數等於1時,所有記錄在統一組內排好序。

            通俗來講,希爾排序就是多次的直接插入排序,不過除了最後一次直接插入排序之外的排序又和原本的直接插入排序有所不同。那麼有的小夥伴看到這裡可能就會問了為什麼要進行多次的插入排序,單次的插入排序又和正常的插入排序不同在哪裡呢?別急,下面我們一個個回答。

            先是為什麼要多次的插入排序,看過上面對於插入排序的特性總結我們會發現,當元素的集合越接近有序,那麼對其進行插入排序的時間效率就越高。因此希爾排序除了最後一次的排序是正常的插入排序之外的多次插入排序的目的就是不斷的調整這個元素的集合,使其不斷的接近有序

            緊接著是希爾排序除最後一次插入排序之外的插入排序與正常插入排序的差異。透過上面對插入排序的學習,我們會發現對於一個亂序的數組的來說,一個元素若想來到正確的位置必須要與其餘元素一一比較,也就是一步步的挪動,這種挪動在數組元素個數少的情況下尚可,但當這個數組的元素個數很多的時候,以升序來說,想像這個數組內最大的元素位於數組的第一個位置,那麼是不是就要將這個元素與數組內其餘元素一一比較以後,才能來到數組的最後一個位置,但當我們加大比較的步伐,也就是增大相比較的兩個元素之間的距離,那麼這個元素是不是就可以更快的來到它應該所處的位置。放置於飛行棋的情境之下,插入排序每次都擲出1,而哈希排序除了最後一次的插入排序擲出的點數是1,其餘的插入排序所擲出的點數是都是大於1的,所以可想而知,哈希排序能夠更快的到達排序的終點。

            為了方便小夥伴們的理解,這部分程式碼共分為兩部分:①固定步伐的直接插入排序②哈希排序。

    先是固定步伐的直接插入排序,先让我们通过图片来直观的看到数组数组内的元素通过这种操作后的变化。

    Java資料結構之插入排序與希爾排序怎麼實現

    //固定步伐的直接插入排序[升序]
    void ShellSort(int* arr, int n)
    {
    	int gap = 3;
    	int end;
    	//有两种写法,看你要控制end,还是des
    	/*for (int i=0; i < n-gap; i++)
    	{
    		int end = i;
    		int des = arr[end + gap];
    		while (end >= 0)
    		{
    			if (des >= arr[end])
    				break;
    			if (des < arr[end])
    			{
    				arr[end + gap] = arr[end];
    				end -= gap;
    			}
    			arr[end + gap] = des;
    		}
    	}*/
     
    	for (int i = gap; i < n ; i++)
    	{
    		int end = i-gap;
    		int des = arr[end + gap];
    		while (end >= 0)
    		{
    			if (des >= arr[end])
    				break;
    			if (des < arr[end])
    			{
    				arr[end + gap] = arr[end];
    				end -= gap;
    			}
    			arr[end + gap] = des;
    		}
    	}
    }
    登入後複製

    接着就是希尔排序

    上述的代码是gap=3的情况下的直接插入排序,那么对于希尔排序而言,我们该对gap该如何选择呢?对于不同gap值的插入排序来说,我们会发现:gap越大,元素跳得越快,数组越不接近有序;而gap越小,元素跳的越慢,数组越接近有序。由于数组的大小不定,因此希尔排序也没有一个合适gap值适用于所有数组,显然,这个gap值一定是动态变化的。

    对于gap的动态变化,常见的有两种:

    ①令gap等于数组的元素个数,每次插入排序后令gap除等2

    ②另一种则是令gap等于数组的元素个数,不过每次插入排序后令gap除以3再加1

    无论哪种处理都能使gap动态变化并最后等于1,对数组进行一次插入排序,达到最后想要的效果。

    代码如下:

    //希尔排序
    void ShellSortPlus(int* arr, int n)
    {
    	int gap=n;
    	int end;
    	while (gap > 1)
    	{
    	gap = gap / 2;
    		
    		for (int i=0; i < n - gap;i++)//有两种写法,看你要控制end,还是des
    		{
    			int end = i;
    			int des = arr[end + gap];
    			while (end >= 0)
    			{
    				if (des >= arr[end])
    					break;
    				if (des < arr[end])
    				{
    					arr[end + gap] = arr[end];
    					end -= gap;
    				}
    				arr[end + gap] = des;
    			}
    		}
     
    	}
    }
    登入後複製

    二、测试代码

    为了方便小伙伴们测试排序后的效果,为大家提供了测试的代码并包含排序的具体代码和包含的头文件。

    #include 
    #include 
    #include 
     
    //插入排序[升序]
    int* InsertSort(int* arr, int n)
    {
     
    	//整体排序
    	for (int i = 1; i < n; i++)
    	{
    		int end = i - 1;
    		int des = arr[i];
    		//单趟排序
    		while (end >= 0)
    		{
    			if (des >= arr[end])
    				break;
    			if (des < arr[end])
    			{
    				arr[end + 1] = arr[end];
    				end--;
    			}
    			arr[end+1] = des;
    		}
    	}
    }
     
    //固定步伐的直接插入排序[升序]
    void ShellSort(int* arr, int n)
    {
    	int gap = 3;
    	int end;
    	//有两种写法,看你要控制end,还是des
    	/*for (int i=0; i < n-gap; i++)
    	{
    		int end = i;
    		int des = arr[end + gap];
    		while (end >= 0)
    		{
    			if (des >= arr[end])
    				break;
    			if (des < arr[end])
    			{
    				arr[end + gap] = arr[end];
    				end -= gap;
    			}
    			arr[end + gap] = des;
    		}
    	}*/
     
    	for (int i = gap; i < n ; i++)
    	{
    		int end = i-gap;
    		int des = arr[end + gap];
    		while (end >= 0)
    		{
    			if (des >= arr[end])
    				break;
    			if (des < arr[end])
    			{
    				arr[end + gap] = arr[end];
    				end -= gap;
    			}
    			arr[end + gap] = des;
    		}
    	}
    }
     
     
    //希尔排序
    void ShellSortPlus(int* arr, int n)
    {
    	int gap=n;
    	int end;
    	while (gap > 1)
    	{
    	gap = gap / 2;
    		
    		for (int i=0; i < n - gap;i++)//有两种写法,看你要控制end,还是des
    		{
    			int end = i;
    			int des = arr[end + gap];
    			while (end >= 0)
    			{
    				if (des >= arr[end])
    					break;
    				if (des < arr[end])
    				{
    					arr[end + gap] = arr[end];
    					end -= gap;
    				}
    				arr[end + gap] = des;
    			}
    		}
     
    	}
    }
     
    //打印排序好的数组
    void PrintSort(int*arr,int n)
    {
    	for(int i=0;i
    登入後複製

    以上是Java資料結構之插入排序與希爾排序怎麼實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    本網站聲明
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

    熱AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智慧驅動的應用程序,用於創建逼真的裸體照片

    AI Clothes Remover

    AI Clothes Remover

    用於從照片中去除衣服的線上人工智慧工具。

    Undress AI Tool

    Undress AI Tool

    免費脫衣圖片

    Clothoff.io

    Clothoff.io

    AI脫衣器

    Video Face Swap

    Video Face Swap

    使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

    熱工具

    記事本++7.3.1

    記事本++7.3.1

    好用且免費的程式碼編輯器

    SublimeText3漢化版

    SublimeText3漢化版

    中文版,非常好用

    禪工作室 13.0.1

    禪工作室 13.0.1

    強大的PHP整合開發環境

    Dreamweaver CS6

    Dreamweaver CS6

    視覺化網頁開發工具

    SublimeText3 Mac版

    SublimeText3 Mac版

    神級程式碼編輯軟體(SublimeText3)

    Java 中的史密斯數 Java 中的史密斯數 Aug 30, 2024 pm 04:28 PM

    Java 史密斯數指南。這裡我們討論定義,如何在Java中檢查史密斯號?帶有程式碼實現的範例。

    Java Spring 面試題 Java Spring 面試題 Aug 30, 2024 pm 04:29 PM

    在本文中,我們保留了最常被問到的 Java Spring 面試問題及其詳細答案。這樣你就可以順利通過面試。

    突破或從Java 8流返回? 突破或從Java 8流返回? Feb 07, 2025 pm 12:09 PM

    Java 8引入了Stream API,提供了一種強大且表達力豐富的處理數據集合的方式。然而,使用Stream時,一個常見問題是:如何從forEach操作中中斷或返回? 傳統循環允許提前中斷或返回,但Stream的forEach方法並不直接支持這種方式。本文將解釋原因,並探討在Stream處理系統中實現提前終止的替代方法。 延伸閱讀: Java Stream API改進 理解Stream forEach forEach方法是一個終端操作,它對Stream中的每個元素執行一個操作。它的設計意圖是處

    Java 中的時間戳至今 Java 中的時間戳至今 Aug 30, 2024 pm 04:28 PM

    Java 中的時間戳記到日期指南。這裡我們也結合範例討論了介紹以及如何在java中將時間戳記轉換為日期。

    Java程序查找膠囊的體積 Java程序查找膠囊的體積 Feb 07, 2025 am 11:37 AM

    膠囊是一種三維幾何圖形,由一個圓柱體和兩端各一個半球體組成。膠囊的體積可以通過將圓柱體的體積和兩端半球體的體積相加來計算。本教程將討論如何使用不同的方法在Java中計算給定膠囊的體積。 膠囊體積公式 膠囊體積的公式如下: 膠囊體積 = 圓柱體體積 兩個半球體體積 其中, r: 半球體的半徑。 h: 圓柱體的高度(不包括半球體)。 例子 1 輸入 半徑 = 5 單位 高度 = 10 單位 輸出 體積 = 1570.8 立方單位 解釋 使用公式計算體積: 體積 = π × r2 × h (4

    PHP與Python:了解差異 PHP與Python:了解差異 Apr 11, 2025 am 12:15 AM

    PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

    PHP:網絡開發的關鍵語言 PHP:網絡開發的關鍵語言 Apr 13, 2025 am 12:08 AM

    PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

    創造未來:零基礎的 Java 編程 創造未來:零基礎的 Java 編程 Oct 13, 2024 pm 01:32 PM

    Java是熱門程式語言,適合初學者和經驗豐富的開發者學習。本教學從基礎概念出發,逐步深入解說進階主題。安裝Java開發工具包後,可透過建立簡單的「Hello,World!」程式來實踐程式設計。理解程式碼後,使用命令提示字元編譯並執行程序,控制台上將輸出「Hello,World!」。學習Java開啟了程式設計之旅,隨著掌握程度加深,可創建更複雜的應用程式。

    See all articles