1. 程式人生 > >數據結構 排序(堆排序)

數據結構 排序(堆排序)

數組 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;
}

技術分享

數據結構 排序(堆排序)