堆:就是完全二叉樹,所以對於堆的儲存可以用順序儲存來儲存堆。這樣便於對堆的便利與操作。
對於具有n個結點的完全二叉樹,如果按照從上至下,從左至右的順序對所有節點從0開始編號,則對於序號為i的節點有:
若i > 0,雙親序號:(i - 1) / 2; i = 0, i為根節點編號,無雙親結點根據這個就可以用順序儲存更好的訪問乙個結點的雙親結點以及孩子結點。若2i + 1 < n,左孩子序號:2i + 1,否則無左孩子結點
若2i + 2 < n,右孩子序號:2i + 2,否則無右孩子結點
堆的基本操作:
這就是堆裡面要進行的操作:
操作的實現:
標頭檔案:heap.h
#ifndef __heap_h__
#define __heap_h__
#include
#include
#include
typedef int hpdatatype;
typedef struct heap
heap;
//初始化堆
void heapinit(heap* ph, hpdatatype* a, int size);
//銷毀堆
void heapdestory(heap* ph);
//向堆裡面插入乙個資料(插入到堆尾)
//刪除乙個資料(也就是刪除堆頂的資料)
//取出堆頂元素
hpdatatype heaptop(heap* ph);
//判斷堆是否為空
int heapempty(heap* ph);
//求堆的大小
int heapsize(heap* ph);
//列印堆
//採用堆排序,從小到大(採用大頂堆)
void heapsortsmalltobig(hpdatatype* a, int size);
//採用堆排序,從大到小(採用小頂堆)
void heapsortbigtosmall(hpdatatype* a, int size);
#endif //__heap_h__
介面實現:
#include "heap.h"
//交換兩個資料
void swap(hpdatatype* a, hpdatatype* b)
//向下調整堆(調為大堆)
//思想:判斷parent與child中較大值的結點的比較,如果parent < child,調整,
//然後在進行剛才調整過的child處的結點,直到葉子節點。結束:葉子節點的孩子結點超出陣列的下標最大值
void adjustdown(hpdatatype* a, int
size, int
parent)
//交換結點,向下調整
if (a[parent] < a[child])
//如果要調整的的這個結點,比起的孩子結點大的話,那就不用調整了
else
}}//對堆進行初始化,也就是要建堆
void heapinit(heap* ph, hpdatatype* a, int n)
ph->_size = n;
ph->_capacity = n;
//調整堆
//思路:從最後乙個非葉子結點開始調整堆(向下調整),結束:調整到堆頂
//雙親結點等於孩子結點減一除以二
//構建堆的時間複雜度為o(n)
for (i = (n - 2) / 2; i >= 0; i--)
}//對堆進行銷毀
//思路:將size變為0,capacity變為0,陣列指標指向的空間變為null
void heapdestory(heap* ph)
//從下到上調整堆
void adjustup(heap* ph, int child)
//如果child小於或者等於parent的話,那就不用調整堆了
else
}}//對堆進行插入乙個元素
//思路:首先要判斷堆對的空間是否已被佔滿,佔滿增容,否則進行插入
//也就是在該堆的最後乙個元素進行插入,然後在進行向上調整
//先插入,從下到上調整堆
//插入
ph->_a[ph->_size] = x;
ph->_size++;
//從下到上調整堆
adjustup(ph, ph->_size - 1);
}//取出堆頂元素
//思路:將堆頂元素與最後乙個元素進行交換,然後再刪除最後乙個元素,對於此時的堆,進行一次,向下調整即可
//返回堆頂元素
hpdatatype heaptop(heap* ph)
//判斷隊是否為空
//空 0
//非空 1
int heapempty(heap* ph)
//求堆的大小
int heapsize(heap* ph)
//堆的輸出函式
printf("\n");
}//堆排序(從小到大) 採用大頂堆
//思想:開始講其變為乙個大頂堆,然後每次將堆頂與最後乙個元素進行交換,在令該隊減少乙個元素再次進行
void heapsortsmalltobig(hpdatatype* a, int
size)
//當size變為0的時候,那麼該堆已經變為了乙個有序的序列了
while (size > 0)
//該函式排序函式的時間複雜度為o(nlogn)
//調整完之後size變為了0,對於這個堆,size還應該是原來的size
size = start_size;
}//小頂堆從上到下,調整
void adjustdownsmallheap(hpdatatype* a, int
size, int
parent)
//交換結點,向下調整
if (a[parent] > a[child])
//如果要調整的的這個結點,比起的孩子結點大的話,那就不用調整了
else
}}//對陣列進行排序(從大到小) 採用小頂堆
void heapsortbigtosmall(hpdatatype* a, int
size)
while (size > 0)
}
測試函式:
test.c
#include "heap.h"
void testheap()
; int size = sizeof(arr) / sizeof(arr[0]);
heapinit(&hp, arr, size);
printf("堆的堆頂元素為:%d\n", heaptop(&hp));
printf("堆的大小:%d\n", heapsize(&hp));
if (heapempty(&hp))
else
//堆排序
//從小到大(大頂堆)
heapsortsmalltobig(hp._a, hp._size);
//從大到小
heapsortbigtosmall(hp._a, hp._size);
heapdestory(&hp);
}int main()
資料結構堆的基本操作實現
堆 其實就是一棵完全二叉樹 見下圖 在陣列中的實現 堆分為大根堆和小根堆 大根堆 1.根節點最大 2.子節點必須大於等於父節點 小跟堆 1.根節點最小 2.子節點必須小於等於父節點 在陣列中儲存這種結構時,總是習慣將根節點儲存在陣列下標為1的位置 每乙個下標為k的節點的父節點的下標就是k 2 每乙個...
資料結構 堆的理解和基本操作
一.堆的概念 如果有乙個關鍵碼的集合k 把他所有元素按照完全二叉樹的順序儲存方式儲存在乙個一維陣列中,並滿足 ki k2 i 1 且 ki k2 i 2 ki k2 i 1 且 ki k2 i 2 i 0,1,2 則稱為小堆 或大堆 小堆 從上圖可以看出小堆的特點是 任意一節點的數值都要大於堆頂的結...
資料結構 堆的操作
堆是指乙個完全二叉樹,它的某個結點的值總是不大於,或不小於其父節點的值,堆分為大堆和小堆,小堆堆頂元素一定是最小的,堆頂到每個葉子結點的路徑是公升序的,大堆則相反。堆的操作主要包括堆的建立,插入元素,刪除元素,返回堆頂元素等操作,其中,堆的建立要用到向下調整演算法,插入要用到向上調整演算法,具體操作...