您的位置:首页 > 运维架构

堆的TopK问题,优先级序列,堆排序d

2018-02-26 20:34 302 查看

堆的概念:

    如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元 素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:   Ki <= K2*i+1 且 Ki<= K2*i+2 (Ki >= K2*i+1 且 Ki >= K2*i+2) i = 0,1,2…,则称为小堆(或大堆)。

    小堆(大堆)中:任一结点的关键码均小于(大于)等于它的左右孩子的关键 码,位于堆顶结点的关键码最小(最大),从根节点到每个结点的路径上数 组元素组成的序列都是递增(递减)的堆存储在下标为0开始的数组中,因此在堆中给定下标为i的结点时

        如果i=0,结点i是根节点,没有双亲节点;否则结点i的双亲结点为 结点(i-1)/2 

        如果2 * i + 1 <= n - 1,则结点i的左孩子为结点2 * i + 1,否则结 点i无左孩子 

        如果2 * i + 2 <= n - 1,则结点i的右孩子为结点2 * i + 2,否则结 点i无右孩子

堆的创建:



void MakeHeap(Datatype *a,size_t n)
{
int i=(n-2)/2;//最后一个节点的父亲
for (;i>=0;i--)
{
AdjustDownS(a,n,i);//向下调整
}
}
void AdjustDownS(Datatype *a,size_t n,int k)//小堆
{
int parent=k;
int child=parent*2+1;
while (child<n)
{
if (a[child+1]<a[child] && child+1<n)//俩个孩子选大的
{
++child;
}
if (a[parent]>a[child])//若父亲大于儿子则交换值
{
Datatype tmp=a[parent];
a[parent]=a[child];
a[child]=tmp;

parent=child;//////
child=parent*2+1;////用依次调整
}
else
{
break;
}
}
}

TopK问题:

首先构建TopK函数:查找最大的前K项 需建立小堆 反之大堆

void TopK(Datatype* a, size_t n, size_t k)//找出最大的前K项
{
int j;
int i=(n-2)/2;
for (;i>=0;i--)//找最大的前K项 需要创建小堆
{
AdjustDownS(a,n,i);
}
for (j=k;j<n;j++)//从K后进行比较
{
if (a[0]<a[j])//大的进行值替换
{
a[0]=a[j];
AdjustDownS(a,k,0);//小堆调整
}
}
for (j=1;j<=k;j++)
{
printf("%d ",a[j-1]);//打印最大的前K项
}
}

TopK问题测试用例:

void Test1()
{
int i;
Datatype a[]={10,11, 13, 12, 16, 18, 15, 17, 14, 19};
Datatype NArray[1000];
srand(time(0));
for (i = 0; i < 1000; ++i)
{
NArray[i] = rand()%10000;
}

NArray[30] = 10001;
NArray[350] = 10002;
NArray[999] = 10003;
NArray[158] = 10004;
NArray[334] = 10005;

TopK(NArray, 1000, 5);

//MakeHeap(a,sizeof(a)/sizeof(a[0]));
}

优先级序列问题:

首先创建结构体:

typedef int Datatype;
typedef struct PriorityQueue
{
Datatype _a
;
size_t _size;
}PriorityQueue;

在一个有序的堆里插入一个数 应用向上调整:

void AdjustUp(Datatype *a,int child)//大堆
{
int parent=(child-1)/2;
while (parent>=0)
{
if (a[parent]<a[child])
{
Datatype tmp=a[parent];
a[parent]=a[child];
a[child]=tmp;

child=parent;
parent=(child-1)/2;
}
else
{
break;
}
}
}

然后是优先级的各种的函数构造:

void PriorityQueueInit(PriorityQueue* q)//优先级初始化
{
assert(q);
memset(q->_a,0,sizeof(Datatype));
q->_size=0;

}
void PriorityQueuePush(PriorityQueue* q, Datatype x)//在一个有序的堆里插入
{
assert(q);
if (q->_size==N)
{
printf("Priority Queue Full!!!\n");
return;
}
q->_a[q->_size]=x;
q->_size++;
AdjustUp(q->_a,q->_size-1);//向上调整大的往上调
}
void PriorityQueuePop(PriorityQueue* q)//出堆 最大的优先出
{
assert(q);
if (q->_size==0)
{
printf("Priority Queue Empty!!!\n");
return;
}
q->_a[0]=q->_a[q->_size];
--q->_size;
AdjustDownD(q->_a,q->_size,0);//出后 进行大堆调整
}
Datatype PriorityQueueTop(PriorityQueue* q)
{
assert(q);
return q->_a[0];
}
size_t PriorityQueueSize(PriorityQueue* q)
{
return q->_size;
}
size_t PriorityQueueEmpty(PriorityQueue* q)
{
assert(q);
return q->_size>0?1:0;
}

优先级测试用例:

void Test2()
{

PriorityQueue q;
PriorityQueueInit(&q);
PriorityQueuePush(&q, 5);
PriorityQueuePush(&q, 2);
PriorityQueuePush(&q, 3);
PriorityQueuePush(&q, 7);
PriorityQueuePush(&q, 6);
PriorityQueuePush(&q, 1);
PriorityQueuePush(&q, 4);

while (PriorityQueueEmpty(&q) != 0)
{
printf("%d ", PriorityQueueTop(&q));
PriorityQueuePop(&q);
}
printf("\n");

}

堆排序问题:

void HeapSort(Datatype* a, size_t n)//升序 堆排序
{
int i,j;
int tmp;
for (i=(n-2)/2;i>=0;i--)
{
AdjustDownD(a,n,i);//如果要构建升序,则需要建大堆
}

for (j=n-1;j>=0;j--)//最大的替换到后边 然后在大堆排序
{
tmp=a[0];
a[0]=a[j];
a[j]=tmp;

AdjustDownD(a,j,0);
}
for (i=0;i<n;i++)
{
printf("%d ",a[i]);
}
}

堆排序测试用例:

void Test3()
{
int i;
Datatype a[]={10,11, 13, 12, 16, 18, 15, 17, 14, 19};
HeapSort(a,sizeof(a)/sizeof(a[0]));

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息