堆及堆排序

堆是一种特殊的数据结构,它是完全二叉树,可以用一维数组来保存,因为二叉树的性质,所以根据数组下标就可以确定位置,下面代码是关于堆的实现, 删除的过程其实就是将堆的根节点取出的过程, 这时的顺序就是有序的, 如果是最小堆,那么就是从小到大排序,反之,就是从大到小

 1 #include <stdio.h>
 2 
 3 int h[101];
 4 int n;
 5 //交换函数
 6 void swap(int a, int b)
 7 {
 8     int t = h[a];
 9     h[a] = h[b];
10     h[b] = t;
11 }
12 //向下调整函数, 调整每个点都满足最小堆的特性
13 void siftDown(int i)
14 {
15     int flag = 0;//用来标记是否需要向下调整
16     int t;
17     while(i * 2 <= n && flag == 0)//如果有孩子并且需要继续调整
18     {
19         if(h[i * 2] < h[i])//左儿子不满足最小堆的关系,交换
20         {
21             t = i * 2;
22         }
23         else
24             t = i;
25         if(i * 2 + 1 <= n)//再比较右儿子
26         {
27             if(h[t] > h[i * 2 + 1])
28             {
29                 t = i * 2 + 1;
30             }
31         }
32         if(t != i)//如果最小的节点不是自己,说明子节点中有比父节点小的
33         {
34             swap(i, t);
35             i = t;
36         }
37         else
38             flag = 1;
39     }
40 }
41 //删除堆的根节点的函数,
42 int deleted()
43 {
44     int t = h[1];
45     h[1] = h[n];//将最后一个移上来, 继续调整,保持最小堆
46     n--;
47     siftDown(1);
48     return t;
49 }
50 //创建堆
51 void create()
52 {
53     for(int i = n / 2; i >= 1; i--)
54         siftDown(i);
55 }
56 
57 int main()
58 {
59     scanf("%d", &n);
60     int num = n;
61     for(int i = 1; i <= n; i++)
62     {
63         scanf("%d", &h[i]);
64     }
65     create();
66     //从小到大输出
67     for(int i = 1; i <= num; i++)
68         printf("%d ", deleted());
69     return 0;
70 }

 上面是一次性的输入数据,当然也可以添加数据,添加数据的时候,只要把数据添加到最后,然后调整顺序使它满足最小堆就行了

代码很简单

 1 //向上调整函数
 2 void siftUp(int i)
 3 {
 4     int flag = 0;
 5     while(i != 1 && flag == 0)
 6     {
 7         if(h[i] < h[i / 2])
 8             swap(i, i / 2);
 9         else
10             flag = 1;
11         i = i / 2;
12     }
13 }

 下面是堆排序的实现,先构造最小堆,然后再堆排序,基本代码类似,就增加了一个堆排序函数,这个函数是将第一个元素,也就是根节点与最后一个交换,那么最后的这个一定是最小的,然后n(总数)--, 这是在调整第一个的位置,使它满足最小堆,一次调整到只剩一个元素就可以了,堆排序的时间复杂度和快排和归并一样都是nlog(n), 也是比较快的排序,下面是堆排序的代码

 1 #include <stdio.h>
 2 
 3 int h[101];
 4 int n;
 5 //交换函数
 6 void swap(int a, int b)
 7 {
 8     int t = h[a];
 9     h[a] = h[b];
10     h[b] = t;
11 }
12 //向下调整函数, 调整每个点都满足最小堆的特性
13 void siftDown(int i)
14 {
15     int flag = 0;//用来标记是否需要向下调整
16     int t;
17     while(i * 2 <= n && flag == 0)//如果有孩子并且需要继续调整
18     {
19         if(h[i * 2] < h[i])//左儿子不满足最小堆的关系,交换
20         {
21             t = i * 2;
22         }
23         else
24             t = i;
25         if(i * 2 + 1 <= n)//再比较右儿子
26         {
27             if(h[t] > h[i * 2 + 1])
28             {
29                 t = i * 2 + 1;
30             }
31         }
32         if(t != i)//如果最小的节点不是自己,说明子节点中有比父节点小的
33         {
34             swap(i, t);
35             i = t;
36         }
37         else
38             flag = 1;
39     }
40 }
41 
42 //创建堆
43 void create()
44 {
45     for(int i = n / 2; i >= 1; i--)
46         siftDown(i);
47 }
48 //堆排序
49 void heapSort()
50 {
51     //依次将第一个与最后一个交换,所以最后一个为最小的
52     while(n > 1)
53     {
54         swap(1, n);
55         n--;//总数减少
56         siftDown(1);
57     }
58 }
59 
60 int main()
61 {
62     scanf("%d", &n);
63     int num;
64     for(int i = 1; i <= n; i++)
65     {
66         scanf("%d", &h[i]);
67     }
68     num = n;
69     create();
70     heapSort();
71     for(int i = 1; i <= num; i++)
72         printf("%d ", h[i]);
73     printf("\n");
74     return 0;
75 }

 附(堆的另一种版本):

#include <cstdio>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;

struct HeapStruct{
    int *Element;
    int Size;
    int Capacity;
};
bool isEmpty(HeapStruct *H)//判断队列是否为空 
{
    return (H->Size == 0);
}
void Insert(HeapStruct *H, int item)//插入函数,将item这个数插入到数列中 
{
    int i;
    H->Size++;
    for (i = H->Size; i > 0; i /= 2)
    {
        if (H->Element[i / 2] >= item)
            break;
        H->Element[i] = H->Element[i / 2];
    }
    H->Element[i] = item;
}
int Delete(HeapStruct *H)//删除堆顶元素 
{
    if (isEmpty(H))
    {
        printf("Heap is empty!\n");
        return 0;
    }
    int child, parent;
    int tmp = H->Element[1];
    int t = H->Element[H->Size--];
    for (parent = 1; parent * 2 <= H->Size; parent = child)
    {
        child = parent * 2;
        if (child != H->Size && H->Element[child] < H->Element[child + 1])
            child++;
        if (t >= H->Element[child])
            break;
        H->Element[parent] = H->Element[child];
    }
    H->Element[parent] = t;
    return tmp;
}
HeapStruct* Build(HeapStruct *H)//当所有的数据都输入到数组的时候,这时候数组还不是堆,要将他调整成堆 
{
    
    int i, parent, child, tmp;
    for (i = H->Size / 2; i > 0; i--)
    {
        tmp = H->Element[i];
        for (parent = i; parent * 2 <= H->Size; parent = child)
        {
            child = parent * 2;
            if (child != H->Size && H->Element[child] < H->Element[child + 1])
                child++;
            if (tmp >= H->Element[child])
                break;
            H->Element[parent] = H->Element[child];
        }
        H->Element[parent] = tmp;
    }
    return H;
}
HeapStruct* Create(int MaxSize)//初始化创建一个大小为MaxSize的堆 
{
    HeapStruct *H = (HeapStruct*) malloc(sizeof(HeapStruct));
    H->Size = 0;
    H->Element = (int *)malloc(sizeof(int) * (MaxSize + 1));
    H->Capacity = MaxSize;
    return H;
}
int Top(HeapStruct *H)//获得堆顶元素 
{
    if (isEmpty(H))
    {
        printf("Queue is null\n");
        return 0;
    }
    return H->Element[1];
}
int main()
{
    int MaxSize;
    int n;
    printf("Input MaxSize:\n");
    scanf("%d", &MaxSize);
    printf("Input n\n");
    scanf("%d", &n);
    HeapStruct *H = Create(MaxSize);
    H->Size = n;
    for (int i = 1; i <= n; i++)
        scanf("%d", &H->Element[i]);
    H = Build(H);
    printf("After build heap:\n");
    for (int i = 1; i <= n; i++)
        printf("%d ", H->Element[i]);
    puts("");
    int t;
    printf("Input you want insert number:\n");
    scanf("%d", &t);
    Insert(H, t);
    printf("After inserted:\n");
    for (int i = 1; i <= H->Size; i++)
        printf("%d ", H->Element[i]);
    puts("");
    printf("After delete the first one: ");
    Delete(H);
    for (int i = 1; i <= H->Size; i++)
        printf("%d ", H->Element[i]);
    puts("");
    printf("Top is: %d\n", Top(H));
    return 0;
}
View Code

 

posted @ 2014-10-19 14:11  Howe_Young  阅读(249)  评论(0编辑  收藏  举报