盐城网站推广网站不备案有什么影响
盐城网站推广,网站不备案有什么影响,wordpress 去优酷广告插件,全球华设计大赛堆的概念
如果有一个关键码的集合K{k0,k1,k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储再一个一维数组中#xff0c;并满足:KiK2i1且KiK2i1(Ki K2i1 且 Ki K2i2),i0,1,2,3…。则称为小堆(或大堆)。将根结点最大的堆叫做最大堆或大根堆#…堆的概念
如果有一个关键码的集合K{k0,k1,k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储再一个一维数组中并满足:KiK2i1且KiK2i1(Ki K2i1 且 Ki K2i2),i0,1,2,3…。则称为小堆(或大堆)。将根结点最大的堆叫做最大堆或大根堆根结点最小的堆叫做最小堆或小根堆
堆的性质
堆中某个节点的值总是不大于或不小于其父节点的值堆总是一棵完全二叉树。
堆的向下调整算法
顺序存储的完全二叉树
已知[parent]
[left] 2*[parent]1;
[right] 2*[parent]2;已知[child] 无论左右
[parent] ([child]-1)/2基本步骤
建立小堆
要调整root所在结点前提:root的左右结点子树已经满足堆的性质如果root所在结点已经是叶子结点调整结束找到左右孩子中最小的一个minif (array[root] array[min])。调整结束else: swap(array[root],array[min]) ; [min] [root] ; 再回到1重复这几个步骤
代码实现
void AdjustDown(int array[], int size, int root)
{//判断 root 是否是叶子结点//因为 堆是完全二叉树所以没有左孩子一定没有右孩子//又因为堆是顺序存储的//所以找到左孩子的下标如果左孩子的下标越界了则没有左孩子while (1){int left 2 * root 1;if (left size){//越界了就是叶子结点return;}//走完上面一定有左孩子判读是否有右孩子//找到左右孩子最小的一个int right 2 * root 2;int min left;//最开始就认为最小的值为左孩子if (right size array[right] array[left]){//没有越界,就有右孩子如果右孩子的值小于左孩子的值min right;}//比较array[min] array[root]if (array[root] array[min]){return;}//调整,交换值int t array[root];array[root] array[min];array[min] t;//需要继续向下调整以min作为结点root min;}
}测试
void PrintArray(int array[], int size)
{for (int i 0; i size; i){printf(% d, array[i]);}printf(\n);
}void TestAdjustDown()
{int array[] { 27, 15, 19, 18, 28, 34, 65, 49, 25, 37 };int size sizeof array / sizeof(int);PrintArray(array, size);AdjustDown(array, size, 0);PrintArray(array, size);
}时间复杂度(logn) 建堆
循环变量i从最后一个非叶子节点开始到0结束在这之间不断的做向下调整
最后一个非叶子节点 最后一个结点的双亲结点( size-1) ((size-1)-1)/2 代码实现
//建堆
void CreateHeap(int array[], int size)
{for (int i (size - 2) / 2; i 0; i--){//不断的向下调整AdjustDown(array, size, i);}
}测试
时间复杂度O(n)
void TestCreateHeap(){int array[] { 15, 37, 2, 45, 63, 9, 18, 7, 16, 13 };int size sizeof(array) / sizeof(int);CreateHeap(array, size);PrintArray(array, size);
}堆的初始化
//初始化
void HeapInit(Heap *heap, int array[], int size){memcpy(heap-array, array, size*sizeof(int));heap-size size;CreateHeap(heap-array, size);
}堆的删除
只能删除堆顶元素删其他位置没有意义拿数组中最后一个元素覆盖掉数组第一个元素也就是堆顶元素然后向下调整
代码实现
//删除
void HeapPop(Heap *heap)
{heap-array[0] heap-array[heap-size - 1];AdjustDown(heap-array, heap-size - 1,0);heap-size--;
}堆的插入
往数组中最后一个位置插入然后向上调整
//向上调整
/*
array 数组
size 数组的长度
child 要向上调整的结点下标
*///小堆的情况
void AdjustUp(int array[], int size, int child)
{while (1){//已经到堆顶位置if (child 0){return;}int parent (child - 1) / 2;//父结点的值比孩子的值小的就不用调整if (array[parent] array[child]){return;}//交换int t array[parent];array[parent] array[child];array[child] t;child parent;}
}/插入操作
void HeapPush(Heap *heap, int val){heap-array[heap-size] val;AdjustUp(heap-array, heap-size, heap-size - 1);
}堆排序
堆排序不能找最小的放到最前要不然堆的结构会被破坏
堆排序的注意事项
排升序建大堆排降序建小堆原因是重新调整回堆的成本更小(向下调整(O(logn)) 建堆(O(n)))
i的意义是被选出的最大的数的个数
for(i size-1){//一次循环找出一个最大的数放到最后swap(array[0],array[size-1-i])AdjustDown(array,size-1-i);
}代码实现
//大堆的情况void AdjustDown222(int array[], int size, int root)
{//判断 root 是否是叶子结点//因为 堆是完全二叉树所以没有左孩子一定没有右孩子//又因为堆是顺序存储的//所以找到左孩子的下标如果左孩子的下标越界了则没有左孩子while (1){int left 2 * root 1;if (left size){//越界了就是叶子结点return;}//走完上面一定有左孩子判读是否有右孩子//找到左右孩子最小的一个int right 2 * root 2;int min left;//最开始就认为最小的值为左孩子if (right size array[right] array[left]){//没有越界,就有右孩子如果右孩子的值小于左孩子的值min right;}//比较array[min] array[root]if (array[root] array[min]){return;}//调整,交换值int t array[root];array[root] array[min];array[min] t;//需要继续向下调整以min作为结点root min;}
}
void AdjustUp222(int array[], int size, int child)
{while (1){//已经到堆顶位置if (child 0){return;}int parent (child - 1) / 2;//父结点的值比孩子的值小的就不用调整if (array[parent] array[child]){return;}//交换int t array[parent];array[parent] array[child];array[child] t;child parent;}
}//堆排序
//升序建大堆void HeapSort(int array[], int size)
{CreateHeap(array, size);//i 表示被找出的最大的数的个数for (int i 0; i size - 1; i){//每次循环会找出最大的一个数放到最后int t array[0];array[0] array[size - i - 1];array[size - i - 1] t;//进行向下调整数据规模是size-1-i;AdjustDown222(array, size - 1 - i, 0);}
}测试
void TestHeapSort()
{int array[] { 39, 129, 12, 38, 27, 9, 33, 2, 14 };int size sizeof(array) / sizeof(int);HeapSort(array, size);PrintArray(array, size);
}测试堆排序与冒泡排序的速度
#define SIZE 50000void TestSortSpeed(){srand(20190104);int array[SIZE] ;for (int i 0; i SIZE; i){array[i] rand() % 10 * 10000;}int s time();HeapSort(array, SIZE);int e time();printf(%d\n, e - s);}堆排序速度 冒泡排序速度
TopK问题
在海量数据中(n100*10000),找最大的k10个数
/*
类似伪代码实际中size是海量的内存中放不下需要借助文件操作
*/
void TopK(int array[], int size, int k){int *heap (int *)malloc(sizeof(int)*k);for (int i 0; i k; i){heap[i] array[i];}//针对heap建小堆CreateHeap(heap, k);for (int j k; j size; j){if (array[j]heap[0]){heap[0] array[j];AdjustDown(heap, k, 0);}}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/90403.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!