亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

c++怎么實現堆排序

發布時間:2022-03-22 16:10:59 來源:億速云 閱讀:131 作者:iii 欄目:大數據

這篇文章主要講解了“c++怎么實現堆排序”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“c++怎么實現堆排序”吧!

一 準備知識

堆的結構可以分為大根堆和小根堆,是一個完全二叉樹,而堆排序是根據堆的這種數據結構設計的一種排序,下面先來看看什么是大根堆和小根堆

1.1 大根堆和小根堆
性質:每個結點的值都大于其左孩子和右孩子結點的值,稱之為大根堆;每個結點的值都小于其左孩子和右孩子結點的值,稱之為小根堆。如下圖

c++怎么實現堆排序

我們對上面的圖中每個數都進行了標記,上面的結構映射成數組就變成了下面這個樣子

c++怎么實現堆排序

還有一個基本概念:查找數組中某個數的父結點和左右孩子結點,比如已知索引為i的數,那么

1.父結點索引:(i-1)/2(這里計算機中的除以2,省略掉小數)

2.左孩子索引:2*i+1

3.右孩子索引:2*i+2

所以上面兩個數組可以腦補成堆結構,因為他們滿足堆的定義性質:

大根堆:arr(i)>arr(2i+1) && arr(i)>arr(2i+2)

小根堆:arr(i)<arr(2i+1) && arr(i)<arr(2i+2)

二 堆排序基本步驟

基本思想:

  1. 首先將待排序的數組構造成一個大根堆,此時,整個數組的最大值就是堆結構的頂端

  2. 將頂端的數與末尾的數交換,此時,末尾的數為最大值,剩余待排序數組個數為n-1

3.將剩余的n-1個數再構造成大根堆,再將頂端數與n-1位置的數交換,如此反復執行,便能得到有序數組

2.1 構造堆

將無序數組構造成一個大根堆(升序用大根堆,降序就用小根堆)

假設存在以下數組

c++怎么實現堆排序

主要思路:第一次保證0~0位置大根堆結構(廢話),第二次保證0~1位置大根堆結構,第三次保證0~2位置大根堆結構...直到保證0~n-1位置大根堆結構(每次新插入的數據都與其父結點進行比較,如果插入的數比父結點大,則與父結點交換,否則一直向上交換,直到小于等于父結點,或者來到了頂端)

插入6的時候,6大于他的父結點3,即arr(1)>arr(0),則交換;此時,保證了0~1位置是大根堆結構,如下圖:

c++怎么實現堆排序

(友情提示:待交換的數為藍色,交換后的數為綠色)

插入8的時候,8大于其父結點6,即arr(2)>arr(0),則交換;此時,保證了0~2位置是大根堆結構,如下圖

c++怎么實現堆排序

插入5的時候,5大于其父結點3,則交換,交換之后,5又發現比8小,所以不交換;此時,保證了0~3位置大根堆結構,如下圖

c++怎么實現堆排序

插入7的時候,7大于其父結點5,則交換,交換之后,7又發現比8小,所以不交換;此時整個數組已經是大根堆結構

c++怎么實現堆排序

2.2 固定最大值再構造堆

此時,我們已經得到一個大根堆,下面將頂端的數與最后一位數交換,然后將剩余的數再構造成一個大根堆

c++怎么實現堆排序

(友情提示:黑色的為固定好的數字,不再參與排序)

此時最大數8已經來到末尾,則固定不動,后面只需要對頂端的數據進行操作即可,拿頂端的數與其左右孩子較大的數進行比較,如果頂端的數大于其左右孩子較大的數,則停止,如果頂端的數小于其左右孩子較大的數,則交換,然后繼續與下面的孩子進行比較

下圖中,5的左右孩子中,左孩子7比右孩子6大,則5與7進行比較,發現5<7,則交換;交換后,發現5已經大于他的左孩子,說明剩余的數已經構成大根堆,后面就是重復固定最大值,然后構造大根堆

c++怎么實現堆排序

如下圖:頂端數7與末尾數3進行交換,固定好7,

c++怎么實現堆排序

剩余的數開始構造大根堆 ,然后頂端數與末尾數交換,固定最大值再構造大根堆,重復執行上面的操作,最終會得到有序數組

c++怎么實現堆排序

三 總結

到這里,大家應該對堆排序都有了自己的見解,我們對上面的流程總結下:

1、首先將無需數組構造成一個大根堆(新插入的數據與其父結點比較)

2、固定一個最大值,將剩余的數重新構造成一個大根堆,重復這樣的過程

四 代碼

代碼中主要兩個方法:

1、將待排序數組構造成一個大根堆(元素上升)

2、固定一個最大值,將剩余的數再構造成一個大根堆(元素下降)

    //堆排序
    public static void heapSort(int[] arr) {
        //構造大根堆
        heapInsert(arr);
        int size = arr.length;
        while (size > 1) {
            //固定最大值
            swap(arr, 0, size - 1);
            size--;
            //構造大根堆
            heapify(arr, 0, size);
 
        }
 
    }
 
    //構造大根堆(通過新插入的數上升)
    public static void heapInsert(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            //當前插入的索引
            int currentIndex = i;
            //父結點索引
            int fatherIndex = (currentIndex - 1) / 2;
            //如果當前插入的值大于其父結點的值,則交換值,并且將索引指向父結點
            //然后繼續和上面的父結點值比較,直到不大于父結點,則退出循環
            while (arr[currentIndex] > arr[fatherIndex]) {
                //交換當前結點與父結點的值
                swap(arr, currentIndex, fatherIndex);
                //將當前索引指向父索引
                currentIndex = fatherIndex;
                //重新計算當前索引的父索引
                fatherIndex = (currentIndex - 1) / 2;
            }
        }
    }
    //將剩余的數構造成大根堆(通過頂端的數下降)
    public static void heapify(int[] arr, int index, int size) {
        int left = 2 * index + 1;
        int right = 2 * index + 2;
        while (left < size) {
            int largestIndex;
            //判斷孩子中較大的值的索引(要確保右孩子在size范圍之內)
            if (arr[left] < arr[right] && right < size) {
                largestIndex = right;
            } else {
                largestIndex = left;
            }
            //比較父結點的值與孩子中較大的值,并確定最大值的索引
            if (arr[index] > arr[largestIndex]) {
                largestIndex = index;
            }
            //如果父結點索引是最大值的索引,那已經是大根堆了,則退出循環
            if (index == largestIndex) {
                break;
            }
            //父結點不是最大值,與孩子中較大的值交換
            swap(arr, largestIndex, index);
            //將索引指向孩子中較大的值的索引
            index = largestIndex;
            //重新計算交換之后的孩子的索引
            left = 2 * index + 1;
            right = 2 * index + 2;
        }
 
    }
    //交換數組中兩個元素的值
    public static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

感謝各位的閱讀,以上就是“c++怎么實現堆排序”的內容了,經過本文的學習后,相信大家對c++怎么實現堆排序這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

c++
AI

来安县| 交口县| 织金县| 安图县| 博客| 南汇区| 临西县| 承德市| 隆昌县| 镇安县| 乐至县| 科尔| 镇江市| 秦皇岛市| 清水县| 普兰店市| 诸城市| 建平县| 邮箱| 巴林右旗| 平顺县| 泽普县| 吉木乃县| 周至县| 西峡县| 文水县| 区。| 鄯善县| 和平县| 辽源市| 苏州市| 平凉市| 澄江县| 天柱县| 永丰县| 文昌市| 华容县| 台北县| 土默特左旗| 莱阳市| 仁布县|