• 堆及堆排序


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

     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("
    ");
    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!
    ");
            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
    ");
            return 0;
        }
        return H->Element[1];
    }
    int main()
    {
        int MaxSize;
        int n;
        printf("Input MaxSize:
    ");
        scanf("%d", &MaxSize);
        printf("Input 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:
    ");
        for (int i = 1; i <= n; i++)
            printf("%d ", H->Element[i]);
        puts("");
        int t;
        printf("Input you want insert number:
    ");
        scanf("%d", &t);
        Insert(H, t);
        printf("After inserted:
    ");
        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
    ", Top(H));
        return 0;
    }
    View Code
  • 相关阅读:
    安卓系统源码编译系列(六)——单独编译内置浏览器WebView教程
    android4.0浏览器在eclipse中编译的步骤
    android.net.wifi的简单使用方法
    android:sharedUserId 获取系统权限
    android 常见死机问题--log分析
    android anr分析方法
    android的logcat详细用法
    Android 设计模式 之 观察者模式
    Android 设计模式 之 单例模式
    android 自定义控件 使用declare-styleable进行配置属性(源码角度)
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/4034860.html
Copyright © 2020-2023  润新知