神奇的二叉堆和const_static的使用

  1. 二叉堆是一种完全的二叉树。它分为两种,大顶堆和小顶堆。小顶堆就是左右节点的值都比根节点大。大顶堆就是左右节点的值都比根节点小。二叉堆是用数组表示最方便的一种二叉树。别的二叉树都是用带有左右指针的数据结构表示的。二叉堆用左右指针表示反而有点使用不方便。我们通过数组的标识符,利用完全二叉树的性质,可以很容易的获得一个节点的左右节点和父亲节点。
  2. 已知节点的位置为num,那么父亲节点为(num-1)/2。左节点为2num+1,右节点为2num+2。涉及的主要算法为两个(1)建立二叉堆(数量为num,小顶堆为例)。从i(1-n(不包含n))开始。每次都intarr[i]和intarr[parent(i)](parent(i)不为0)比较。intarr[i]<intarr[parent(i)],则交换两个位置的值,然后i=parent(i)(parent(i)不为0),1-n-1挨次遍历完毕,完成二叉堆的建立。
  3. (2)插入数据num,首先比较intarr[0]和num,num大,则交换num和intarr[0]的值。
  4. 对二叉树进行调整。t=0.挨个比较左右节点的值是否比intarr[t]小,小的话,优先交换右节点。交换完成后,t=rightchild(t)(t<n),然后在进行比较即可,直到调整整个二叉堆。
  5. 整体的实现代码如下:
  6. #include
    #include
    #include
    #define NUM 50
    using namespace std;
    int intarr[NUM];
    int parent(int n)
    {
    return (n - 1) / 2;
    }
    int leftChild(int n)
    {
    return 2 * n + 1;
    }
    int rightChild(int n)
    {
    return 2 * n + 2;
    }
    void buildHeap(int n)
    {
    for (int i = 1; i < n; i++)
    {
    int ti = i;
    while (ti !=0 && intarr[parent(ti)] > intarr[ti])
    {
    int temp = intarr[parent(ti)];
    intarr[parent(ti)] = intarr[ti];
    intarr[ti] = temp;
    ti = parent(ti);
    }
    }
    }
    void insertNumber(int n, int i)
    {
    if (intarr[i] < intarr[0])
    {
    return;
    }
    else
    {
    int temp = intarr[0];
    intarr[0] = intarr[i];
    intarr[i] = temp;
    int ti = 0;
    while ((leftChild(ti) < n && intarr[leftChild(ti)] < intarr[ti]) ||
    (rightChild(ti) < n && intarr[rightChild(ti)] < intarr[ti]))
    {
    if (rightChild(ti) < n && intarr[rightChild(ti)] < intarr[ti])
    {
    int temp = intarr[rightChild(ti)];
    intarr[rightChild(ti)] = intarr[ti];
    intarr[ti] = temp;
    ti = rightChild(ti);
    }
    else
    {
    int temp = intarr[leftChild(ti)];
    intarr[leftChild(ti)] = intarr[ti];
    intarr[ti] = temp;
    ti = leftChild(ti);
    }
    }
    }
    }
    int main()
    {
    srand((unsigned)time(NULL));
    for (int i = 0; i < NUM; i++)
    {
    int val = rand() % 100;
    intarr[i] = val;
    cout << val << " ";
    if ((i + 1) % 10 == 0)
    {
    cout << endl;
    }
    }
    cout << endl;
    int n = 10;
    buildHeap(n);
    for (int i = 10; i < NUM; i++)
    {
    insertNumber(n, i);
    }
    for (int i = 0; i < n; i++)
    {
    cout << intarr[i] << " ";
    }
    cout << endl;
    system(“pause”);
    return 0;
    }
    输出结果:
    在这里插入图片描述
    复杂度分析,如果我们找一个M数组的前N个大的数据。采用循环操作,复杂度为MN。而二叉堆的复杂度为MlogN。
    const_cast可以把一些const的属性的变量为我所用并做一些修改再使用(当然原变量是不修改的),const_cast只允许转换为指针或者引用的变量哦(只有这两个可以转换)。
    #include
    using namespace std;
    int main()
    {
    const int a = 10;
    int *p = const_cast<int *>(&a);
    *p = *p + 20;
    cout << p << endl;
    cout << a << endl;
    system(“pause”);
    return 0;
    }
    执行结果
    30
    10
    说明const_cast是不修改原变量的值得。
    引用的使用:
    #include
    using namespace std;
    int main()
    {
    const int a = 10;
    int &p = const_cast<int &>(a);
    p = p + 20;
    cout << p << endl;
    cout << a << endl;
    system(“pause”);
    return 0;
    }
    执行结果:
    30
    10
    当const的变量为map类型的时候,需要特殊的操作技巧:
    #include
    #include
    using namespace std;
    int main()
    {
    typedef map<int, int> mapInt;
    const mapInt maptest= { {1,5},{2,6},{3,7},{4,8} };
    auto num = maptest[1];
    system(“pause”);
    return 0;
    }
    直接这么来会报:
    错误 C2678 二进制“[”: 没有找到接受“const mapInt”类型的左操作数的运算符(或没有可接受的转换) myConst d:\cpp11_futrue\test-96-myconst\myconst\myconst\myconst.cpp 8
    我们可以这么处理一下:
    #include
    #include
    using namespace std;
    int main()
    {
    typedef map<int, int> mapInt;
    const mapInt maptest= { {1,5},{2,6},{3,7},{4,8} };
    auto num = (
    (const_cast<mapInt *>(&maptest)))[1];
    //auto num = (const_cast<mapInt &>(maptest))[1];
    cout<<num<<endl;
    system(“pause”);
    return 0;
    }
    执行结果:
    5
    很神奇
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值