說說堆及堆排序

堆:是一種數組對象,它可以被看成是一種二叉樹結構。

我們把堆的二叉樹存儲方式分為兩種:即大堆和小堆。那么問題來了,什么大堆?什么是小堆?

大堆:讓每個父節點的值都大于孩子節點的值。

小堆:讓每個父節點的值都小于孩子節點的值。


說完概念后,就來考慮一下如何來實現大堆和小堆吧。第一步肯定得有一個堆吧,所以我們首先得建堆,這是毋庸置疑的。由于堆實際上就是一個二叉樹結構,所以先將數壓進棧中,然后通過向下調整來建大堆。

第一例:堆的實現

具體實現代碼如下:

#pragma once 
#include<vector>
#include<iostream>
#include<assert.h>
using namespace std;
//仿函數用于下面的父節點與子節點的比較
template<class T>
struct Less
{bool operator()(const T& left,const T& right){return (left < right);}};template<class T>
struct Greater
{bool operator()(const T& left,const T& right){return (left > right);}};template<class T,class  Compare = Greater<T>>
class Heap
{
public:
<span style="white-space:pre">	</span>//建堆Heap(const T* a,size_t size){assert(a);for(size_t i = 0; i < size; i++){_a.push_back(a[i]);}for(size_t i = (_a.size()-2)/2; i > 0; i--){AdjustDown(i);}}void push(const T& x){_a.push_back(x);AdjustUp(_a.size()-1);}void pop(){assert(!_a.empty());swap(_a[0],_a[_a.size()-1]);_a.pop_back();AdjustDown(0);}bool Empty(){return _a.empty();}size_t Size(){return _a.size();}void print(){for(size_t i = 0; i < _a.size(); i++){cout<<_a[i]<<" ";}cout<<endl;}
protected:
<span style="white-space:pre">	</span>//向下調整void AdjustDown(size_t parent){size_t child = parent*2+1;Compare com;while(child < _a.size()){if(child+1 < _a.size() && com(_a[child+1],_a[child])){child++;}if(com(_a[child],_a[parent]))     //孩子節點大于父節點{swap(_a[child],_a[parent]);parent = child;child = parent*2+1;}else{break;}}}<span style="white-space:pre">	</span>//向上調整void AdjustUp(size_t child){size_t parent = (child-1)/2;Compare com;while(child > 0){if(com(_a[child],_a[parent]))      //父節點小于孩子節點{swap(_a[child],_a[parent]);child = parent;parent = (child-1)/2;}else{break;}}}
protected:vector<T> _a;
};
void testHeap()
{int a[] = {10,11, 13, 12, 16, 18, 15, 17, 14, 19};Heap<int,Greater<int>> hp(a,sizeof(a)/sizeof(a[0]));hp.push(2);hp.print();
}


第二例:

同樣,我們也可以實現堆排序:

如圖實現方式:



? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

? ? ? ? ? ? ? ? (1)



(2)

? ??? ? ?

(3)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ...

依此向下調整的方式進行排序。

void AdjustDown(int a[],int n, int parent){int child = parent*2+1;while(child < n){if(child+1 < n && a[child+1] > a[child]){child++;}if(a[child] > a[parent]){swap(a[child],a[parent]);parent = child;child = parent*2+1;}else{break;}}}void HeapSort(int a[],size_t n){assert(a);for(int i = (n-2)/2; i >= 0; --i){AdjustDown(a,n,i);}for(int i = 0; i < n; ++i){ swap(a[0],a[n-1-i]);             //交換堆頂元素和最后一個元素AdjustDown(a,n-1-i,0);           //將最后一個元素固定,向下調整前n-i-1個}}void print(int a[],size_t size){for(size_t i = 0; i < size;i++){cout<<a[i]<<" ";}cout<<endl;}
	void TestHeapSort()
{int a[] = {2,1,4,5,0,6,3,7,8,9};HeapSort(a, sizeof(a)/sizeof(a[0]));print(a,sizeof(a)/sizeof(a[0]));
}

堆的實現及堆排序就說到這里啦。。堆排序將會在后期排序那部分再與大家見面哦。到時候會與其他排序一起比較,包括它的時間復雜度和空間復雜度,以及各個排序算法的優缺點。今天的就說到這里啦~~吐舌頭吐舌頭




本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/382875.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/382875.shtml
英文地址,請注明出處:http://en.pswp.cn/news/382875.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

運算符優先級 速查表

運算符優先級 優先級【高到低】&#xff1a; 第一級&#xff1a; 圓括號【&#xff08;&#xff09;】、下標運算符【[]】、分量運算符的指向結構體成員運算符【->】、結構體成員運算符【.】 第二級&#xff1a; 邏輯非運算符【!】、按位取反運算符【~】、自增自減運…

linux--幾種常見的進程調度算法

進程調度&#xff1a;在操作系統中調度是指一種資源分配&#xff0c;因而調度算法是指:根據系統的資源分配策略所規定的資源分配算法。操作系統管理了系統的有限資源&#xff0c;當有多個進程(或多個進程發出的請求)要使用這些資源時&#xff0c;因為資源的有限性&#xff0c;必…

指針數組和數組指針和函數指針

文章目錄1.指針數組和數組指針1.int *p1[10];2.int (*p2)[10];2.函數指針char *(*fun1)(char * p1,char *p2)函數指針的概念函數指針的作用&#xff1a;例子1 .調用方式例子2&#xff1a;&#xff08;帶注釋&#xff09;例子33.做題的小技巧1.指針數組和數組指針 1.int *p1[10…

使用虛擬環境virtualenv 創建虛擬環境出現PermissionError: [Errno 13] Permission denied:

使用虛擬環境virtualenv 創建虛擬環境出現PermissionError: [Errno 13] Permission denied: 原因&#xff1a;虛擬環境安裝的目錄所屬用戶非當前用戶 解決辦法&#xff1a;將目錄及其文件的所有者改為當前用戶 解決命令&#xff1a;sudo chown -R 當前用戶 待更改用戶的目錄/ …

linux之父子進程的輸出

首先&#xff0c;我們來回憶一下父進程與子進程&#xff0c;前幾節講了如何創建子進程&#xff0c;像這樣的&#xff0c;pid_t id fork(); 這樣我們就創建好了一個子進程&#xff0c;然而fork()函數的返回值是什么呢&#xff1f;這里要記住&#xff1a;子進程返回0&#xff0c…

linux---談談vfork和fork的區別及exit與return

fork()&#xff1a;創建子進程的函數&#xff0c;是大家比較熟悉的吧。pid_t id fork(); 這里的vfork();也是創建子進程的函數。現在我們來剖析一下它們吧。 第一例&#xff1a; 先看一個fork()的例子哦。 對于fork()而言&#xff0c;創建子進程成功后直接打印出父子進程執…

在MySQL數據庫建立多對多的數據表關系

轉載自 https://blog.51cto.com/13145200724/1370753

C語言模擬實現標準庫函數之qsort()

qsort 編譯器函數庫自帶的快速排序函數。 void qsort(void*base,size_t num,size_t width,int(__cdecl*compare)(const void*,const void*)); 參數解釋&#xff1a; void*base-待排序數組首地址size_t num-數組中待排序元素數量size_t width-各元素的占用空間大小int(__cde…

django contrib 包簡介

轉自 https://www.cnblogs.com/tianboblog/p/6955297.html

linux之管道

管道&#xff08;PIPE&#xff09;是linux中一個重要的通信方式&#xff0c;在進程中&#xff0c;我們通過從一個進程中讀取到的數據轉到另一個進程中的寫數據中&#xff0c;這時就要有不同的進程之間共享同一份資源&#xff0c;就是所謂的進程間通信。由于進程的特點是資源獨占…

把student a am i 變成 i am a student(兩種方法)

文章目錄#student a am i 變成 i am a student##方法1&#xff1a;指針#include <stdlib.h> #include <stdio.h> #include <string.h>void fanw(char *l, char *r) {char* left l;char* right r;char temp;while (left < right){temp *left;*left *ri…

關掉占用 某端口的進程

sudo fuser -k 8000/tcp 這樣和端口8000相關的進程就都關了。

linux之多線程(1)

我們之前講了進程&#xff0c;今天我們重新認識另外一個概念---線程。我們首先會想到的是進程和線程有什么區別和聯系&#xff0c;對吧&#xff1f;進程是由程序執行起來&#xff0c;跑在操作系統的&#xff0c;是系統進行資源分配和調度的基本單位。進程具有資源獨占性&#x…

C語言typedef與#define的區別

typedef和#define define 沒有參加編譯&#xff0c;在預處理的時候就被替換掉了。 typedef參加編譯和鏈接。typedef是重命名&#xff0c;可以為枚舉結構體等等重新命名&#xff0c;提高代碼整潔。 一、typedef的用法 C語言中&#xff0c;typedef常用來定義一個標識符及關鍵…

django models模型 內部類 class Meta 簡介

class Meta: #這個屬性是定義當前的模型類是不是一個抽象類。所謂抽象類是不會相應數據庫表的。一般我們用它來歸納一些公共屬性字段&#xff0c;然后繼承它的子類能夠繼承這些字段。abstractTrue #db_table是用于指定自己定義數據庫表名的db_table test#因為Django的管理方法…

阻斷血緣關系以及checkpoint文件清理

spark-sql讀寫同一張表&#xff0c;報錯Cannot overwrite a path that is also being read from 1. 增加checkpoint&#xff0c;設置檢查點阻斷血緣關系 sparkSession.sparkContext.setCheckpointDir("/tmp/spark/job/OrderOnlineSparkJob")val oldOneIdTagSql s&…

linux之睡眠函數(my_sleep)

我們在程序中&#xff0c;很多次用到sleep()函數&#xff0c;讓它睡眠幾秒后再執行該進程。今天呢&#xff0c;我要給大家實現一下sleep函數。 看看代碼哦&#xff1a; 運行結果&#xff1a; 結果中每隔三秒鐘&#xff0c;打印一條語句。實現了sleep(3)的功能。 關于sleep函數…

C語言 防止頭文件被多次引用

comm.h和comm.c是公共模塊。 test1.h和test1.c使用了公共模塊。 test2.h和test2.c使用了了公共模塊。 test.h和test.c使?用了了test1模塊和test2模塊。 這樣最終程序中就會出現兩份comm.h的內容。這樣就造成了了文件內容的重復。 1.方法1 文件開頭加上這一句就ok #prag…

python字符串切片操作

name abcdefghijk name[2:-1] cdefghijname[2:] cdefghijk # 第三個參數是步長 name[2:-1:2] cegi# 字符串反轉 name[::-1] name[-1::-1] kjihgfedcba kjihgfedcba

機器思維。一些讓我眼前一亮的算法。

用人腦相處了計算機處理數據的方式。而不是 人腦處理的方式—>用計算機的語言表達 人腦處理的方式—>計算機處理的方式—>用計算機的語言表達