深信服笔试

 

1 struct还有这种神奇的初始化方式:

struct node{
    int v1;
    int v2;
}t{1};
//t.v1 = 1
tt{1, 2};
//tt.v1 = 1  tt.v2 = 2

2 static声明的局部变量 默认初始化

static int sss;

3 堆

一个初始堆是一个完全二叉树

举例说明:

给定一个整形数组a[]={16,7,3,20,17,8},对其进行堆排序。

首先构建一个二叉树:

然后我们希望调整出一个大顶堆

则从最后一个非叶结点开始调整,过程如下:

找到 节点、左孩子、右孩子 三者中的最大值,放到节点位置上

继续调整该节点父节点之间的位置关系:

后头发现,16 与 17关系不满足,继续自上而下调整它

这样就得到了初始堆 而且还是个 大顶堆

即每次调整都是从父节点、左孩子节点、右孩子节点三者中选择最大者跟父节点进行交换(交换之后可能造成被交换的孩子节点不满足堆的性质,因此每次交换之后要重新对被交换的孩子节点进行调整)。有了初始堆之后就可以进行排序了。

下面开始排序了!

 

20  17  8  7  16  3

 

把第一个和最后一个元素交换       3    17    8    7  16  20     得到最大元素 20   因为之前已经保证了 堆顶元素最大

去掉最后一个元素 & 调整 得到   :   17  10  8    7    3     

 

把第一个和最后一个元素交换:    3  10  8  7  17        得到最大元素 17   因为之前已经保证了 堆顶元素最大 

去掉最后一个元素 & 调整 得到   :  10  7  3  8

 

把第一个和最后一个元素交换:    8    7  3  10           得到最大元素 10   因为之前已经保证了 堆顶元素最大 

去掉最后一个元素 & 调整 得到   :  8  7  3  

 

把第一个和最后一个元素交换:    3  7  8              得到最大元素 8     因为之前已经保证了 堆顶元素最大 

去掉最后一个元素 & 调整 得到   :   7   3          

 

把第一个和最后一个元素交换:    3  7                得到最大元素 7     因为之前已经保证了 堆顶元素最大 

去掉最后一个元素 & 调整 得到   :   3

 

把第一个和最后一个元素交换:   3                得到最大元素 3     因为之前已经保证了 堆顶元素最大 

去掉最后一个元素 & 调整 得到   :  空                END : 结束排序

 

实现了:

#include <iostream>
#include <cstdio>
#include <cstring>
#define LS(x) x << 1
#define RS(x) x << 1 | 1
using namespace std;

template<class T>
void updateMaxHeap(T *a, int i, int n)
{
    int left = LS(i), right = RS(i), largest;
    if(left > n) return ;
    largest = left;
    if(right <= n && a[right] > a[largest]){
        largest = right;
    }
    if(a[i] < a[largest]){  // 孩子 大于 父节点 需要调整
        swap(a[i], a[largest]);
        updateMaxHeap(a, largest, n);
    }//如果根节点最大 那么不用继续调整下去了
}

template<class T>
void create_max_heap(T *a, int n)
{
    // 1...n/2 是树中所有非叶子结点 只需要调整非叶子节点即可
    // 倒着调整建堆:这点很重要!
    for(int i = n/2; i >= 1; i --){
        updateMaxHeap(a, i, n);
    }
}

template<class T>
void heap_sort(T *a, int n)
{

    create_max_heap(a, n);
    cout<<"Max Heap: "<<endl;
    for(int i = 1; i <= n; i ++)
        cout<<a[i]<<" ";
    for(int i = n; i >= 2; i --){
        swap(a[i], a[1]);
        updateMaxHeap(a, 1, i - 1);
    }
    cout<<"Sort: "<<endl;
    for(int i = 1; i <= n; i ++)
        cout<<a[i]<<" ";
}

double nums[100];
int main()
{

    int n;
    cin>>n;
    for(int i = 1; i <= n; i ++)
        cin>>nums[i];
    heap_sort(nums, n);
    return 0;
}
//1 5 4 2 3 6

 最后时间复杂度:

  建堆O(n*log2n)

  筛选法调整堆O(log2n)

  总共循环了n-1次调整函数,所以调整堆时间复杂度为O(n*log2n)

  熟悉了堆排序的过程后,可以发现堆排序不存在最佳情况,待排序序列是有序或者逆序时,并不对应于堆排序的最佳或最坏情况。且在最坏情况下时间复杂度也是O(n*log2n)。此外堆排序是不稳定的原地排序算法。

posted on 2017-03-22 19:29  暴力的轮胎  阅读(406)  评论(0编辑  收藏  举报

导航