大根堆:
根結點(稱為堆頂)的關鍵字是堆裡所有結點關鍵字中最大者,稱為大根堆,又稱最大堆(大頂堆)。大根堆要求根節點的關鍵字既大於或等於左子樹的關鍵字值,又大於或等於右子樹的關鍵字值。
heap是一種資料結構具有以下的特點:
1) 完全二叉樹;
2)heap中儲存的值是偏序;
小根堆(最大堆): 父節點的值小於或等於子節點的值;
大根堆(最小堆): 父節點的值大於或等於子節點的值;
堆的儲存
一般都用陣列來表示堆,i結點的父結點下標就為(i–1)/2。它的左右子結點下標分別為2 * i + 1和2 * i + 2。如第0個結點左右子結點下標分別為1和2。
堆排序堆建好之後堆中第0個資料是堆中最大的資料。取出這個資料再執行下堆的刪除操作。這樣堆中第0個資料又是堆中最大的資料,重複上述步驟直至堆中只有乙個資料時就直接取出這個資料。
堆的操作:insert
插入乙個元素:新元素被加入到heap的末尾,然後更新樹以恢復堆的次序。
每次插入都是將新資料放在陣列最後。可以發現從這個新資料的父結點到根結點必然為乙個有序的數列,現在的任務是將這個新資料插入到這個有序資料中——這就類似於直接插入排序中將乙個資料併入到有序區間中。
堆的操作:removemax
按定義,堆中每次都刪除第0個資料。為了便於重建堆,實際的操作是將最後乙個資料的值賦給根結點,然後再從根結點開始進行一次從上向下的調整。調整時先在左右兒子結點中找最大的,如果父結點比這個最小的子結點還大說明不需要調整了,反之將父結點和它交換後再考慮後面的結點。相當於從根結點將乙個資料的「下沉」過程。
/*** 實驗題目:
* 從大資料檔案中挑選k個最小的記錄
* 實驗目的:
* 掌握外排序的過程及堆的應用演算法設計
* 實驗內容:
* 編寫程式,從大資料檔案中挑選k個最小的記錄。假設記憶體工作區的大小為k,
* 模擬這個過程,並輸出每趟的結果。假設整數序列為(15, 4, 97, 64, 17, 32, 108,
* 44, 76, 9, 39, 82, 56, 31, 80, 73, 255, 68),從中挑選5個最小的整數。
* 備註:
* 為了簡單,假設每個記錄僅僅包含整型關鍵字,用全域性變數fi模擬存放所有的記錄,
* r[1..k]存放大根堆。
*/#include
#include
#define max_size (100)
#define max_key (32767) // 最大關鍵字值∞
#define k 5 // 記憶體工作區可容納的記錄個數
typedef int key_type; // 關鍵字型別
typedef struct
file_type; // 檔案型別
file_type fi; // 定義輸入檔案,為全域性變數
key_type r[k + 1]; // 存放大根堆
/*------------------輸入檔案初始化-------------------*/
static void initial(void)
;for(i = 0; i < n; i++) // 將n個記錄存放到輸入檔案中
fi.recs[i] = a[i];
fi.length = n; // 輸入檔案中有n個記錄
fi.cur_rec = -1; // 輸入檔案中當前位置為-1
}/*-------------------從輸入檔案中取乙個記錄r--------------------*/
static bool get_one_rec(key_type &r)
}/*-------------------顯示堆中所有記錄--------------------*/
static void disp_heap(void)
/*---------------篩選為大根堆演算法------------------*/
static void sift(int low, int high)
else
break; // 篩選結束
}r[i] = tmp; // 被篩選結點的值放入最終位置
}/**
* 功能:
* 從輸入檔案fi中挑選k個最小的記錄。
* 演算法思路:
* 首先,從fi中取出開頭的k個記錄存放在r中,將其調整為乙個大根堆r,
* 然後依次取出fi的其餘記錄r,若r小於大根堆r的根結點r[1],用r替代r[1],
* 再篩選為大根堆。當fi所有記錄取出完畢,r中即為k個最小的記錄。
*/static void select_k(void)
for(i = k / 2; i >= 1; i--) // 建立初始堆 i = 2, 1
sift(i, k);
printf("開頭%d個記錄建立的大根堆:", k);
disp_heap();
while(get_one_rec(r)) // 從輸入檔案fi中取出其餘的記錄
else
printf("\t不需要篩選\n");}}
int main(void)
測試結果:
開頭5個記錄建立的大根堆:97 64 15 4 17
處理32: 需要篩選,結果:64 32 15 4 17
處理108: 不需要篩選
處理44: 需要篩選,結果:44 32 15 4 17
處理76: 不需要篩選
處理9: 需要篩選,結果:32 17 15 4 9
處理39: 不需要篩選
處理82: 不需要篩選
處理56: 不需要篩選
處理31: 需要篩選,結果:31 17 15 4 9
處理80: 不需要篩選
處理73: 不需要篩選
處理255: 不需要篩選
處理68: 不需要篩選
最終結果: 31 17 15 4 9
大資料檔案讀取方法
filepath 1.txt step 1024 1024 1m str r n start 0 i 1 count 0 do while i 1 echo count file get contents 讀取大檔案方法 param unknown patha 檔案路徑 param unknown ...
批量去重大資料檔案
作為乙個linux的學徒,分享一下自己解決這個小問題的心得,在處理這個問題時使用了乙個小技巧感覺很適用,個人發覺linux的終端真滴是非常強大,下面就詳細地介紹這個問題以及解決辦法吧 問題描述 由於要分析登入ip所以有很多放有不同ip的日誌檔案,首先要將所有log檔案合併成乙個log檔案,並將每乙個...
C 從資料夾中讀取txt資料檔案
txt檔案的命名以數字遞增的方式來命名,樣例如下 資料檔案放在工程下,讀取的思路是 先獲取資料夾下的檔案的數量,然後以數字自增的方式獲取檔案的名稱 使用tostring 方法 具體 如下 提取資料,讀到arraylist al中 元素為每一行的資料 private void read string ...