堆排序与新元素插入(对应王道考研数据结构)

代码:主要针对王道的代码增加了新元素的插入(上浮)操作

#include<iostream>
#include<algorithm>

using namespace std;

typedef int ElemType;
/*
三个主要构成
1.初始建堆函数(编号<=n/2的所有结点依次进行“下沉”调整(自底向上处理各分支结点)
2.调整函数(小元素不断下沉的调整法 重点)
3.全过程函数-先初始建堆,再进行A[1]和A[i]的交换,然后继续对换上去的堆顶元素使用调整函数(下沉调整整个堆)
*/

void HeapAdjust(ElemType A[],int k,int len){  //将坐标为k的子树根下沉
        int i;
        A[0]=A[k]; //A[0]暂存子树的根节点
        for(i=2*k;i<=len;i*=2){
            if(i<len&&A[i]<A[i+1])  //先比较一下根节点k的左右子节点的大小,以确认和哪个互换
                i++;   
            if(A[0]>=A[i]) break; //不需要交换,筛选结束    
            else{
                A[k]=A[i]; //与较大的交换
                k=i;   //修改k值,继续将坐标k元素下沉
            }
        }
        A[k]=A[0]; //找到最终位置后,将最开始传入的A[k]放入现在应该有的位置
}

void Heapadjust(ElemType A[],int k){ //将坐标为k的子树根上浮(用于插入)注意此时的特性是新插入结点一定是叶子结点
    int i;
    A[0]=A[k]; 
    // printf("A[k]的值是%d\n",A[k]);
    for(i=k/2;i>0;i/=2){
        if(i<=0 || A[i]>=A[0]) break;
        else{
            // printf("A[i]值是%d \n",A[i]);
            A[k]=A[i];
            k=i;
        }
    }
    A[k]=A[0];
}

void BuildMaxHeap(ElemType A[],int len){  //初始建堆
    for(int i=len/2;i>0;i--)  HeapAdjust(A,i,len); //A[0]始终留着
}

void HeapSort(ElemType A[],int len){
    int j;
    BuildMaxHeap(A,len); //建堆-O(n)
    for(j=len;j>1;j--){
        swap(A[j],A[1]);
        HeapAdjust(A,1,j-1);
    }
}
void HeapInsert(ElemType A[],int e,int len){ //将一个新元素插入到大(小)根堆中
     A[++len]=e;
     Heapadjust(A,len);
}
void printArray(ElemType A[],int n){
    for(int i=1;i<=n;i++){
        printf("%d ",A[i]);
    }
    printf("\n");
}

测试1(对大(小)根堆插入(上浮)一个新元素)时间复杂度与树的高度h有关,根据完全二叉树的性质:O( l o g 2 n log_2^{n} log2n)

int main(){
    int A[11]={0,2,3,4,1,2,4,5,8,6,14};
    printArray(A,10);
    BuildMaxHeap(A,10);
    printArray(A,10);
    HeapInsert(A,7,10);
    printArray(A,11);
    return 0;
}

测试2(堆排序)-时间复杂度 O ( n ) + O ( n l o g 2 n ) = O ( n ) O(n)+O(nlog_2^{n})=O(n) O(n)+O(nlog2n)=O(n)

int main(){
    int A[11]={0,2,3,4,1,2,4,5,8,6,14};
    printArray(A,10);
	HeapSort(A,10);
    printArray(A,10);
    return 0;
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值