icoding测试代码--堆

本代码适用于

 堆初始化在本例已经内置,无需添加。

icoding的数据结构并没有一个测试代码,其都是直接编写一个函数的形式,因此很难知道自己的实际输出是什么。针对部分题目,我编写了一系列测试代码以供大家进行数据输出的测试。

//堆辅助函数
int parent(int i) //返回堆元素数组下标为 i 的结点的父结点下标
{
//TODO
}
int left(int i)  //返回堆元素数组下标为 i 的结点的左子结点下标
{
//TODO
}
int right(int i)  //返回堆元素数组下标为 i 的结点的右子结点下标
{
//TODO
}
void swap_node(MinHeapNode *x, MinHeapNode *y)  //交换两个堆元素的值
{
//TODO
}

//堆插入
bool heap_insert_value(PMinHeap pq, int value)
{
//TODO
}

//堆化
void min_heapify(PMinHeap pq, int i){
//todo
}

请将您的函数代码复制到上述函数中,然后修改main函数的相关内容,完成测试样例的输入

因为技术受限,只能以列表形式输出结果,暂不能以树状形式输出,请谅解~

#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<string.h>


typedef struct _otherInfo
{
    int i;
    int j;
}OtherInfo;

typedef struct _minHeapNode
{
    int value;
    OtherInfo otherInfo;
}MinHeapNode, *PMinHeapNode;

typedef struct _minPQ {
    PMinHeapNode heap_array; // 指向堆元素数组
    int heap_size; // 当前堆中的元素个数
    int capacity;  //堆数组的大小
}MinHeap, *PMinHeap;


//初始化最小堆
void init_min_heap(PMinHeap pq, int capacity){
   pq->capacity=capacity;
   pq->heap_size=0;
   pq->heap_array=(PMinHeapNode)malloc(capacity*sizeof(MinHeapNode));
}
//打印堆
void print_min_heap(PMinHeap pq){
    printf("heap_size:%d\t",pq->heap_size);
    printf("capacity:%d\n",pq->capacity);
    printf("序号|\tval\ti\tj\n");
    printf("--------------------------------\n");

    for(int i=0;i<pq->heap_size;i++){
        if(i<10)
        printf("[%d] |\t%d\t%d\t%d\n",i,pq->heap_array[i].value,pq->heap_array[i].otherInfo.i,pq->heap_array[i].otherInfo.j);
        else
        printf("[%d]|\t%d\t%d\t%d\n",i,pq->heap_array[i].value,pq->heap_array[i].otherInfo.i,pq->heap_array[i].otherInfo.j);
    }
    printf("\n");
}
//从数组中堆元素插入
bool heap_insert_value_fromarr(PMinHeap pq, int val[],int other_i[],int other_j[]){
    if(pq->heap_size==pq->capacity){
        printf("堆已满!程序自动终止,请增大capacity的值\n");
        return false;
    }
    pq->heap_size++;
    int i=pq->heap_size-1;
    pq->heap_array[i].value=val[i];
    pq->heap_array[i].otherInfo.i=other_i[i];
    pq->heap_array[i].otherInfo.j=other_j[i];
    while(i!=0&&pq->heap_array[i].value<pq->heap_array[(i-1)/2].value){
        MinHeapNode temp=pq->heap_array[i];
        pq->heap_array[i]=pq->heap_array[(i-1)/2];
        pq->heap_array[(i-1)/2]=temp;
        i=(i-1)/2;
    }
    return true;
}
//无序堆的插入
bool heap_insert_nosort_fromarr(PMinHeap pq, int val[],int other_i[],int other_j[]){
    if(pq->heap_size==pq->capacity){
        printf("堆已满!程序自动终止,请增大capacity的值\n");
        return false;
    }
    pq->heap_size++;
    int i=pq->heap_size-1;
    pq->heap_array[i].value=val[i];
    pq->heap_array[i].otherInfo.i=other_i[i];
    pq->heap_array[i].otherInfo.j=other_j[i];
    while(i!=0&&i!=1&&i!=2&&pq->heap_array[i].value<pq->heap_array[(i-1)/2].value){
        MinHeapNode temp=pq->heap_array[i];
        pq->heap_array[i]=pq->heap_array[(i-1)/2];
        pq->heap_array[(i-1)/2]=temp;
        i=(i-1)/2;
    }
    return true;
}
//查找标号为i的元素
PMinHeapNode heap_find_node(PMinHeap pq,int i){
    if(i>=pq->heap_size){
        //printf("未找到元素%d!\n",i);
        return NULL;
    }
    return &pq->heap_array[i];
}





//------------------以上为辅助函数------------------


int parent(int i){
        //TODO
}

int left(int i){
    //TODO
}

int right(int i){
   //TODO
}

void swap_node(MinHeapNode *x, MinHeapNode *y){
   //TODO
  
}


bool heap_insert_value(PMinHeap pq, int value){
	//TODO
}

void min_heapify(PMinHeap pq, int i){
	//TODO
}


int main(){
//-------------以 下 内 容 可 以 修 改------------------
    int val[]={607, 136, 333, 170,54, 275, 527, 743, 506, 927, 572, 952};
    int other_i[]={1,2,3,4,5,6,7,8,9,10,11,12};
   
    //以上分别代表堆的值,和其对应的i,j(见结构体的OtherInfo)
    //为了方便大家,我们把i,j的值都设置成了i的值;即 other_j[]的值与other_i[]的值相同,您只需定义other_i[]即可
    //icoding会检查i,j的值是否匹配,所以对于辅助函数题目的swap函数不要只交换value哦

    //必须保证数组的长度小于堆的容量
    //保证三个数组的值相等
    //【重要】您无需在意数组的顺序是否满足递增/递减,对于辅助函数、堆插入这两个题目我们会自动为排序,初始化的堆一定是最小堆;
    //对于堆化题目,题目意思是,根节点左右两棵子树均满足最小堆要求,但整颗树因为有根节点所以不满足,需要调整根节点。
    //本程序在运行堆化题目时,默认第一个节点(根节点)不动,但自动排列生成根节点左右子树均满足最小堆的堆。您也无需在意数组的单调性。
    //总而言之,您可以随意输入数据,我们会自动按照题目相关要求生成对应的正确最小堆。
    //对于第三题,我们也提供了一些已经成型的除了根节点外均满足最小堆(即根节点的左右子树都满足最小堆)的数组排列

    

    //第三题的val测试数据
    // (1) 7, 130, 128, 171, 204, 377, 569, 259, 290, 358, 629, 799, 518, 747, 576, 984, 742, 871, 432, 586, 499, 748, 926
    // 数据长度为23  
    // (2) 7, 130, 128, 171, 204, 377, 569, 259
    //  数据长度为8 
    // (3) 2 28, 34, 131, 228, 129, 838, 374, 858, 266, 645, 531
    //  数据长度为12 
    // (4) 363, 158, 239, 372, 280, 508, 693
    //  数据长度为7  
    // (5) 607, 136, 54, 333, 170, 275, 527, 743, 506, 927, 572, 952
    //  数据长度为12 


    int capacity=50;//堆的容量,建议比val大一点,以顺利完成插入。
    //您也可以修改capacity以检查当容量超出时相关函数的返回是否正常,但icoding不测试这一点。

    bool assist_flag=true;//辅助函数题目是否测试,true为测试,false为不测试
    int test_num=2;//辅助函数,parent/left/right函数传入值
    int swap_test_1=1;//辅助函数,swap_node函数要交换的节点的序号(数组下标)
    int swap_test_2=2;//辅助函数,swap_node函数要交换的节点的序号(数组下标)
    //swap_test_1和swap_test_2的值不能相同

    bool insert_falg=true;//heap_insert_value函数是否测试,true为测试,false为不测试
    int insert_test_num=50;//heap_insert_value函数要插入的值,擦入的ij值默认是0

    bool min_heapify_flag=true;//min_heapify函数是否测试,true为测试,false为不测试
    //第三题传入的int数据 min_heapify_test_num 默认为0,暂时不支持调整。
    //他的意思是:根节点(0号节点)这个节点不满足最小堆的要求,需要调整。但根节点的左右子树各自满足最小堆的要求。
    对于堆化题目,题目意思是,根节点左右两棵子树均满足最小堆要求,但整颗树因为有根节点所以不满足,需要调整根节点。
    //icoding测试样例传入的int的数据也是均为0

//-------------以 上 内 容 可 以 修 改------------------

    printf("icoding\n排序-堆\n----开始测试----\n");
    int len_i=sizeof(other_i)/sizeof(int);
    int other_j[len_i];
    //初始化other_j
    for(int i=0;i<len_i;i++)
        other_j[i]=other_i[i];

    
    int len_j=sizeof(other_j)/sizeof(int);
    int len=sizeof(val)/sizeof(int);
    //检测三个数组的长度是否相等
    if(len!=len_i||len!=len_j||len_i!=len_j){
        printf("val/other_i/other_j数组长度不相等!程序自动终止,请修改\n其中,val共计%d个元素,other_i共计%d个元素,other_j共计%d个元素\n",len,len_i,len_j);
        return 0;
    }
    //检测堆是否超出容量
    if(len>capacity){
        printf("堆容量不足!初始化的数据已经大于堆的容量了!程序自动终止,请修改capacity\n您输入的数据容量为%d,堆的容量为%d.建议容量比数据至少多1(即%d),以方便添加元素\n",len,capacity,len+1);
        return 0;
    }
    
    
    printf(">>正在初始化堆(堆初始化函数无需完成,本例已内含初始化代码)\n");
    PMinHeap pq=(PMinHeap)malloc(sizeof(MinHeap));
    init_min_heap(pq,capacity);
    printf("##提示:\n对于辅助函数、堆插入的题目,我们已经自动建立了有序的堆;\n对于堆化,我们是根据数组的顺序依次初始化无序堆,需要自己调用你编写的堆化函数使其变成有序堆\n");
    //printf("\n>>正在插入初始化数据\n");
    for(int i=0;i<len;i++){
        heap_insert_value_fromarr(pq,&val[0],&other_i[0],&other_j[0]);
    }

    

    printf("-------------\n");
    if(assist_flag){
        //检查parent/left/right函数是否正确
        int test=rand()%9+1;
        if(parent(test)!=(test-1)/2||left(test)!=2*test+1||right(test)!=2*test+2){
            printf("\n\n!!!您的parent/left/right 函数错误,请您修改!!!\n但程序仍然执行相关函数\n\n");
        }
    }
    if(assist_flag){
    printf(">>打印初始化堆\n");
    print_min_heap(pq);

    
    printf(">>辅助函数,test_num为%d\n",test_num);
    printf("parent返回:%d\t 正确结果:%d\t%s\n",parent(test_num),(test_num-1)/2,parent(test_num)==(test_num-1)/2?"true":"false");
    printf("left返回  :%d\t 正确结果:%d\t%s\n",left(test_num),2*(test_num)+1,left(test_num)==2*(test_num)+1?"true":"false");
    printf("right返回 :%d\t 正确结果:%d\t%s\n",right(test_num),2*(test_num)+2,right(test_num)==2*(test_num)+2?"true":"false");
    PMinHeapNode swap_test_node1=heap_find_node(pq,swap_test_1);
    PMinHeapNode swap_test_node2=heap_find_node(pq,swap_test_2);

        if(swap_test_node1==NULL||swap_test_node2==NULL){
            printf("swap_test_1/2在堆中找不到,请修改!本次跳过swap_node函数的测试\n");
            
        }
        else if(swap_test_1==swap_test_2){
            printf("swap_test_1/2为相同的元素,请修改!本次跳过swap_node函数的测试\n");
        }
        else{
        swap_node(swap_test_node1,swap_test_node2);//两个参数为指针
        printf("swap_node :\n已经交换标号[%d]与[%d]的节点\n\n",swap_test_1,swap_test_2);
        print_min_heap(pq);
        printf("请检查val && i && j的值是否正确交换\n将重新初始化堆。本次交换仅为临时存储。后续测试基于最初的堆\n");
        
            //重新初始化
            init_min_heap(pq,capacity);
            for(int i=0;i<len;i++){
            heap_insert_value_fromarr(pq,&val[0],&other_i[0],&other_j[0]);
            }
            printf("堆已经重新初始化\n");
        }
        
        
    }else{
        printf("辅助函数跳过测试,若需要请修改assist_flag\n后续题目中若需要用到辅助函数,请务必保证完成正确的编写。否则可能导致出错\n");
    }
    
    printf("------------\n");
    if(insert_falg){
        printf(">>打印初始化堆\n");
        print_min_heap(pq);
        
        printf(">>正在插入元素%d\n",insert_test_num);
          //检查容量是否足够插入
        if(len==capacity){
            printf("堆容量可能不足!\n测试的数据容量为%d,堆的容量为%d,现在还额外需要一个容量以插入(即%d)\n插入可能无法正常进行,但函数仍然会运行\n",len,capacity,len+1);
        }
        heap_insert_value(pq,insert_test_num);
        printf(">>插入完成\n");
        print_min_heap(pq);
    }else{
        printf("insert_test_num跳过测试,若需要请修改insert_falg\n");
    }

    printf("------------\n");
    if(min_heapify_flag){
        //检查parent/left/right函数是否正确
        int test=rand()%10;
        if(parent(test)!=(test-1)/2||left(test)!=2*test+1||right(test)!=2*test+2){
            printf("\n\n!!!您的parent/left/right 函数错误,请您修改!!!\n但程序仍然执行相关函数\n\n");
        }
    }
    if(min_heapify_flag){
        init_min_heap(pq,capacity);
        printf(">>正在初始化非根节点数据(根节点的左右两子树均为有序最小堆,但含根节点的整棵树可能无序)\n##本题题意是,根节点左右两棵子树均满足最小堆要求,但整颗树因为有根节点所以不满足\n您需要调整根节点,使得整颗树满足最小堆要求。\n");
        for(int i=0;i<len;i++){
            heap_insert_nosort_fromarr(pq,&val[0],&other_i[0],&other_j[0]);
        }
        printf(">>打印初始化堆(根节点的左右两子树均为有序最小堆,但含根节点的整棵树可能无序)\n");
        print_min_heap(pq);
        int min_heapify_test_num=0;//min_heapify函数要调整的节点的序号,默认都是0,不建议改
        printf(">>正在调整堆\n");
        min_heapify(pq,min_heapify_test_num);
        printf(">>调整完成\n");
        print_min_heap(pq);
    }else{
        printf("min_heapify_flag跳过测试,若需要请修改min_heapify_flag\n");
    }


    printf("\n\n----测试结束----\n");
    return 0;


}

若有任何操作的疑问可以看文章 如何使用测试代码 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谨慎谦虚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值