堆是一棵完全二叉树,树中的每个结点都不小于或不大于左右孩子结点的值。如果父亲结点的值大于孩子结点的值,那么称为大顶堆,反之称为小顶堆。其中大顶堆用于实现优先队列。
可以用数组来进行存储:由二叉树性质可以知道,对于结点i,其左孩子为2*i,右孩子为2*i+1;
int heap[100] , n=10;
建堆时,对非叶子结点进行向下调整downAdjust,使得父节点的值大于左右孩子结点的值。
void downAdjust(int low, int high)
{
int i= low,j=2*i; //i为父节点,j为左孩子
while(j<= high){ //存在孩子结点
if(j+i<=high&& heap[j+1]>heap[j])
{
j=j+1;
}//让j为孩子中最大的那个
if(heap[j]>heap[i])
{
swap(heap[j],heap[i]);
i = j;
j = i * 2;
}else{
break;
}
}
}
对于完全二叉树,其叶子结点的个数为n/2向上取整 ,
void createHeap(){
for(int i = n/2;i >= 1; i--)
{
downAdjust(1,n);
}
}
//删除的时候,用末尾元素覆盖堆顶,并向下调整
void deleteTop(){
heap[1]= heap[n];
n--;
downAdjust(1,n);
}
往堆末尾插入元素的时候,进行向上调整,将插入元素与父亲结点比较,若大于则交换。
void upAdjust(int low,int high){
int i=high;j=i/2; //i为想要调整的结点,j为其父节点
while(j>=low){
if(heap[j]<heap[i])
{
i = j;
j = i/2;
}else{
break;
}
}
}
堆排序:
void HeapSort()
{
createHeap(); //1、先建最大堆
for(int i= n;i >1; i--)
{
swap(heap[1],heap[n]); //交换堆顶元素
downAdjust(1,i-1); //调整堆顶
}
}
快排:每次排序,取一个数temp,使得分完之后左边的数都小于temp,右边的数都大于temp
int partition(int A[], int left, int right)
{
int temp = A[left];
while(left<right){
while(left< right && A[right] >= temp) right--;
A[left]=A[right];
while(left<right && A[left]<=temp ) left++;
A[right]=A[left];
}
A[left]= temp;
return left ;// 返回左右相遇的下标
}
void quickSort(int A[],int left, int right)
{
if(left<right){
int pos = partition(A,left,right);
quickSort(A,left,pos -1);
quickSirt(A,pos+1,right);
}
}