數據結構 排序(堆排序)
阿新 • • 發佈:2017-07-16
數組 char warning gin swa for 剔除 子節點 根節點
//最小堆的特性說明:即任何一非葉節點的值不大於其左右孩子節點的值。 //堆排序最適合取TOPN的數據 #include "myheap.h" int myswap(int *src, int *desc) { int tmp = 0; tmp = *src; *src = *desc; *desc = tmp; return 0; } //調整樹 //@arr 需要排序的數組 //@root 根節點 //@size 樹的大小 int changeTree(int *arr,int root, int size) { int leftnode = 2 * root;//左孩子節點序號int rightnode = 2 * root + 1;//右孩子節點序號 int pos = 0;//孩子節點中值最大的序號 int tmp = 0; if (leftnode > size) { //左孩子的序號大於整個樹的節點數,這是非法的 return -1; } if (rightnode > size) { //這顆樹只有左孩子節點 pos = leftnode; } else { //左孩子右孩子節點都存在,取左孩子右孩子節點中值最大的節點pos = arr[leftnode - 1] < arr[rightnode - 1] ? leftnode : rightnode; } //調整堆 if (arr[root - 1] > arr[pos - 1]) { myswap(arr + root - 1, arr + pos - 1); //重新調整樹 changeTree(arr, pos, size); } return 0; } //創建堆 int buildHeap(int *arr) { //創建最小堆//找到整個樹末尾的非葉子節點 正好是 樹的節點數/2 int pos = K / 2; for (pos; pos >= 1; pos--) { //一開始為無序一組數,需要構建堆,堆需要滿足堆的特性 changeTree(arr, pos, K); } return 0; } //堆排序 //@source 無序數組 //@desc 最終生成TOP N數組 //@size 無序數組的長度 //註意:desc數據就是從source中直接截取N個數據,source不能再有desc的數據,是截取,而不是拷貝 int heapSort(int *source,int *desc,int size) { int i = 0; buildHeap(desc); //樹的堆排序--無序數組中的數據向有序數組中插入 for (i = 0; i < size; i++) { //如果堆中最小的值的節點,說明N數組中有更大的值,將當前堆中的最小值從堆剔除 //並且將N數組中大的值加進來,重新調整堆 if (desc[0] < source[i]) { myswap(desc, source + i); //重新調整堆,因為根節點的值變了,導致堆不再是堆了,所以從根節點開始 changeTree(desc,1, K); } } //註意:堆排序只能獲取海量數組前TOPN的數據,但是TOP N的數組不是有序的,繼續才能獲取完整的序列 //推薦:小數據完全有序,不建議使用堆排序,經過我的測試,似乎速度並不快,可以使用快速排序 for ( i = K-1; i > 0; i--) { //這樣堆頂元素又不是最小的了 //desc[i]=desc[0]; myswap(desc, desc + i); //重新調整堆--本質上堆變小了 changeTree(desc, 1, i); } return 0; }
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "myheap.h" #define NUMCOUNT 100*10000 int getTimestr(char * buf) { time_t tData = 0; //獲取當前系統時間 time(&tData); //定義時間結構體變量 struct tm * eventTime = NULL; //將time_t類型轉化成時間結構體類型 eventTime = localtime(&tData); //tm_year表示年份,以1900為標準,1900的值是0,1901的值是1 int iyear = eventTime->tm_year + 1900; //tm_mon表示月份,從0開始到11結束,按照通常習慣應該從1月份開始 int imon = eventTime->tm_mon + 1; //tm_wday:表示一個星期的第幾天 從1開始7結束 //tm_yday:表示一年的第幾天 //tm_mday:表示正常的月天數 int iday = eventTime->tm_mday; //時分秒 int ihour = eventTime->tm_hour; int imin = eventTime->tm_min; int isec = eventTime->tm_sec; //拼接時間 char timestr[30] = { 0 }; sprintf(timestr, "%04d-%02d-%02d %02d:%02d:%02d", iyear, imon, iday, ihour, imin, isec); strcpy(buf, timestr); return 0; } //隨機產生100萬數據 int createNumber(int *arr) { int i = 0; //定義一個時間類型 time_t ts;//頭文件time.h //生成隨機數種子 srand((unsigned int)(time(&ts))); //創建出5個大數 arr[0] = 10001; arr[1] = 10002; arr[2] = 10005; arr[3] = 10007; arr[4] = 10009; for (i = 5; i < NUMCOUNT; i++) { //隨機產生1000以內的樹 arr[i] = (int)(rand() / 1000); } return 0; } void test() { int i = 0; char timebuf[1024] = { 0 }; int desc[K] = { 2,3,4,5 }; int *soruce = (int *)malloc(sizeof(int)*NUMCOUNT); if (NULL == soruce) { perror("malloc"); return; } memset(soruce, 0, sizeof(int)*NUMCOUNT); createNumber(soruce); getTimestr(timebuf); printf("begin=%s\n", timebuf); heapSort(soruce, desc, NUMCOUNT); for (i = 0; i < K; i++) { printf("%d\n",desc[i]); } memset(timebuf,0,1024); getTimestr(timebuf); printf("end=%s\n", timebuf); free(soruce); soruce = NULL; } int main() { test(); system("pause"); return 0; }
數據結構 排序(堆排序)