一般用陣列來表示堆,i結點的父結點下標就為(i–1)/2。它的左右子結點下標分別為2i+1和2i+2。如第0個結點的左右子結點下標分別為1和2。
1、堆的定義
n個元素的序列當且僅當滿足下列關係之一時,稱之為堆。
情形1:ki <= k2i 且ki <= k2i+1 (最小化堆或小頂堆)
情形2:ki >= k2i 且ki >= k2i+1 (最大化堆或大頂堆)
其中i=1,2,…,n/2向下取整;
2,堆的插入
每次插入都是將先將新資料放在陣列最後,由於從這個新資料的父結點到根結點必然為乙個有序的序列,現在的任務是將這個新資料插入到這個有序序列中——這就類似於直接插入排序中將乙個資料併入到有序區間中。
3. 堆的刪除
堆中每次都只能刪除堆頂元素。為了便於重建堆,實際的操作是將最後乙個資料的值賦給根結點,然後再從根結點開始進行一次從上向下的調整。調整時先在左右子結點中找最小的,如果父結點比這個最小的子結點還**明不需要調整了,反之將父結點和它交換後再考慮後面的結點。相當於根結點資料的「下沉」過程。
4. 堆的建立
從無序序列建堆的過程就是乙個反覆調整的過程。若將此序列看成是乙個完全二叉樹,則最後乙個非終端結點是第(n-2)/2個結點,由此調整過程只需從該結點開始,直到堆頂元素。
5. 堆排序
若在輸出堆頂的最小值之後,使得剩餘n-1個元素的序列重建乙個堆,則得到n個元素中的次小值。如此反覆執行,便能得到乙個有序序列,這個過程稱之為堆排序。
輸出堆頂元素之後,以堆中最後乙個元素替代之,此時根結點的左右子樹均為堆,則僅需進行一次從上到下的調整即可重建乙個堆。
**
#include
#include
#define init_array_size 50
int heap_size;
//堆大小
int heap_cap_size;
//堆容量大小
/*函式宣告*/
//構建堆
void
build_heap
(int array,
int length)
;//堆的調整
void
max_heap_adjust
(int array,
int index)
;//堆的刪除
void
heap_delete
(int array,
int value)
;//堆的插入
void
heap_insert
(int
** array,
int value)
;//堆排序
void
heap_sort
(int array,
int length)
;/*返回以index為根的完全二叉樹的左子樹的索引,整個二叉樹索引以0為開始*/
intleft
(int index)
/*返回以index為根的完全二叉樹的右子樹的索引,整個二叉樹索引以0為開始*/
intright
(int index)
/*兩個數的交換*/
void
swap
(int
* a ,
int* b)
void
build_heap
(int array,
int length)
}void
max_heap_adjust
(int array,
int index)
//右子樹和父節點進行對比
if(right_index <=
(heap_size-1)
&& array[right_index]
> array[largest])if
(largest == index)
else
}void
heap_delete
(int array,
int value)
} array[index]
= array[heap_size -1]
;--heap_size;
max_heap_adjust
(array, index);}
void
heap_insert
(int
** array,
int value)
(*array)
[heap_size]
= value;
//一定要記得加上()既(*array)[heap_size] 如果寫出*array[heap_size]肯定會出問題
index = heap_size;
heap_size++
;//要記得這裡堆大小變大了
//和父節點對比,哪個大就往上移動
while
(index)
index = parent_index;}}
void
heap_sort
(int array,
int length)
//恢復堆的大小
heap_size = old_heap_size;
}void
print_array
(int
* a ,
int length)
printf
("\n");
}int
main()
;int
*array =
null
; array =
(int*)
malloc
(init_array_size*
sizeof
(int))
;int length =
sizeof
(a)/
sizeof
(int);
printf
("陣列的長度是:%d\n"
, length)
;for
(i =
0; i < length;
++i)
printf
("原始陣列為\n");
print_array
(array, length)
;printf
("堆的建立後的陣列\n");
build_heap
(array, length)
;print_array
(array, length)
;printf
("堆排序後的陣列為\n");
heap_sort
(array, length)
;print_array
(array, length)
;//這個地方一定要記得先構建堆,不然下面執行刪除和插入有問題
build_heap
(array, length)
;printf
("刪除資料10後的陣列\n");
heap_delete
(array,10)
; length--
;print_array
(array, length)
;printf
("插入資料10後的陣列\n");
length++
;heap_insert
(&array,10)
;print_array
(array, length)
;printf
("堆排序後的陣列為\n");
heap_sort
(array, length)
;print_array
(array, length)
;return0;
}
單鏈表基本操作 資料結構
鍊錶是一種物理儲存結構上非連續 非順序的資料儲存結構,資料元素的邏輯順序是通過鍊錶中的指標鏈結次序來形成的。單鏈表分為兩種 帶頭節點和不帶頭結點。在這裡,主要介紹不帶頭結點的單鏈表的基本操作。標頭檔案 slist.h typedef int sdatatype typedef struct slis...
資料結構樹的基本操作 資料結構 樹的基本操作
include include include gtree.h include linklist.h typedefstruct tag gtreenode gtreenode 樹的節點 struct tag gtreenode gtreedata data 節點自身資料 gtreenode par...
順序棧的基本操作 資料結構 一 棧結構
數 結 structure data 據 構 棧 結 構 s t a c k 前言 在計算機中儲存資料需要用到各種資料結構,一起來了解下棧結構吧。棧結構介紹 棧結構的宗旨就是先進後出 filo,first in last out 即先進入棧中的元素會在最後才能彈出。棧結構用圖形來表達的話就是這樣 棧...