首页 > 其他分享 >王道408--数据结构--用数组实现二叉树--并查集及其优化代码

王道408--数据结构--用数组实现二叉树--并查集及其优化代码

时间:2023-08-07 10:24:13浏览次数:39  
标签:return idx -- 查集 len int IsEmpty 二叉树 TreeNode

一、数组实现二叉树(下标从0开始)

#include <stdio.h>
typedef struct _TreeNode{
    int data;
    bool IsEmpty;       //结点是否为空  // 因为我们的二叉树不一定是满二叉树,中间可能有一些节点不存在 // 值为1代表空
}TreeNode;


// 初始化
void InitTreeNode(TreeNode t[],int len){
    for(int i=0;i<len;i++)
        t[i].IsEmpty = 1;
}


bool IsEmpty(TreeNode t[],int len,int idx){
    if(idx >= len || idx < 0) return 1;         // 修改为0
    
    return t[idx].IsEmpty;
}

// father = (child-1)/2   or  father = child/2 - 1
int findFather(TreeNode t[],int len,int idx){
    if(idx == 0) return -1;         //特判根节点没有父节点      // 特判也修改为0
    int fatheridx = (idx-1) / 2;
    if(IsEmpty(t,len,fatheridx)) return -1;
    return fatheridx;
}

// lchild = father*2 + 1
int findLchild(TreeNode t[],int len,int idx){
    int lchild = idx*2 + 1;
    if(IsEmpty(t,len,lchild)) return -1;
    return lchild;
}

// rchild = father*2+2
int findRchild(TreeNode t[],int len,int idx){
    int rchild = idx*2 + 2;
    if(IsEmpty(t,len,rchild)) return -1;
    return rchild; 
}

//实现前序遍历, 从下表为idx的节点开始前序遍历
int PreorderTree(TreeNode t[],int len,int idx){
    if(IsEmpty(t,len,idx)) return 0;
    printf("%d\n",t[idx].data);
    PreorderTree(t,len,findLchild(t,len,idx));
    PreorderTree(t,len,findRchild(t,len,idx));
    return 0;
}

int InorderTree(TreeNode t[],int len,int idx){
    if(IsEmpty(t,len,idx)) return 0;
    InorderTree(t,len,findLchild(t,len,idx));
    printf("%d\n",t[idx].data);
    InorderTree(t,len,findRchild(t,len,idx));
    return 0;
}
int PostorderTree(TreeNode t[],int len,int idx){
    if(IsEmpty(t,len,idx)) return 0;
    PostorderTree(t,len,findLchild(t,len,idx));
    PostorderTree(t,len,findRchild(t,len,idx));
    printf("%d\n",t[idx].data);
    return 0;
}


int main(){
    TreeNode Td[100];            // 这里的二叉树节点要从0开始
    int fatheridx;
    int testLen = 7;          // IsEmpty 的判断是 >=Len 所以这里加一个1
    for(int i=0;i<=testLen;i++){
        Td[i].data = i+1;
        Td[i].IsEmpty = 0;
    }
    PreorderTree(Td,testLen,0);
    // InorderTree(Td,testLen,0);
    // PostorderTree(Td,testLen,0);
    return 0;
}

二、数组实现二叉树(下标从1开始)

#include <stdio.h>
typedef struct _TreeNode{
    int data;
    bool IsEmpty;       //结点是否为空  // 因为我们的二叉树不一定是满二叉树,中间可能有一些节点不存在 // 值为1代表空
}TreeNode;


// 初始化
void InitTreeNode(TreeNode t[],int len){
    for(int i=0;i<len;i++)
        t[i].IsEmpty = 1;
}


bool IsEmpty(TreeNode t[],int len,int idx){
    if(idx >= len || idx < 1) return 1;
    
    return t[idx].IsEmpty;
}

// father = child / 2
int findFather(TreeNode t[],int len,int idx){
    // if(idx == 1) return -1;         //特判根节点没有父节点 ,不加也没事,但下表从0开始的时候必须加
    int fatheridx = idx / 2;
    if(IsEmpty(t,len,fatheridx)) return -1;
    return fatheridx;
}

// lchild = father*2
int findLchild(TreeNode t[],int len,int idx){
    int lchild = idx*2;
    if(IsEmpty(t,len,lchild)) return -1;
    return lchild;
}

// rchild = father*2+1
int findRchild(TreeNode t[],int len,int idx){
    int rchild = idx*2+1;
    if(IsEmpty(t,len,rchild)) return -1;
    return rchild; 
}

//实现前序遍历, 从下表为idx的节点开始前序遍历
int PreorderTree(TreeNode t[],int len,int idx){
    if(IsEmpty(t,len,idx)) return 0;
    printf("%d\n",t[idx].data);
    PreorderTree(t,len,findLchild(t,len,idx));
    PreorderTree(t,len,findRchild(t,len,idx));
    return 0;
}

int InorderTree(TreeNode t[],int len,int idx){
    if(IsEmpty(t,len,idx)) return 0;
    InorderTree(t,len,findLchild(t,len,idx));
    printf("%d\n",t[idx].data);
    InorderTree(t,len,findRchild(t,len,idx));
    return 0;
}
int PostorderTree(TreeNode t[],int len,int idx){
    if(IsEmpty(t,len,idx)) return 0;
    PostorderTree(t,len,findLchild(t,len,idx));
    PostorderTree(t,len,findRchild(t,len,idx));
    printf("%d\n",t[idx].data);
    return 0;
}


int main(){
    TreeNode Td[100];            // 这里的二叉树节点要从一开始
    int fatheridx;
    int testLen = 7+1;          // IsEmpty 的判断是 >=Len 所以这里加一个1
    for(int i=1;i<=testLen;i++){
        Td[i].data = i;
        Td[i].IsEmpty = 0;
    }
    PreorderTree(Td,testLen,1);
    // InorderTree(Td,testLen,1);
    // PostorderTree(Td,testLen,1);
    return 0;
}

三、并查集及其优化思路

#include <stdio.h>
#define MAXSIZE 50
int UFSets[MAXSIZE];

void InitUFSets(int S[]){
    for(int i=0;i<MAXSIZE;i++){
        S[i] = -1;
    }
}

int find(int S[],int x){
    if(S[x] == -1) return x;           // -1说明到底了
    return find(S,S[x]);
}

int pathCompFind(int S[],int x){         // 路径压缩策略优化Find 操作
    if(S[x] >= 0){
        S[x] = find(S,S[x]); 
        return S[x];
    }
    return x;
}


bool UnionElem(int S[],int elem1,int elem2){    //王道书上是直接合并的root,而不是元素成员
    int first = find(S,elem1);
    int second = find(S,elem2);
    if(first != second){
        printf("%d -- %d\n",first,second);
        S[second] = first;
        return 1;
    }
    return 0;
}

bool UnionRoot(int S[],int Root1,int Root2){
    if(Root1 == Root2) return 0;    //比较两个根是否来自同一集合
    S[Root2] = Root1;               // 将根Root2连接到Root1上
    return 1;
}

bool optUnionRoot(int S[],int Root1,int Root2){
    if(Root1 == Root2) return 0;
    if(S[Root2] > S[Root1]){   // Root2 结点数更少         // 因为初始化的时候S的值全为 -1  所以 若S[Root1]与S[Root2]相加后为更小的负数
                                                            //较小的树,树较大,这也是为什么 S[Root1] >= S[Root2]时 却把Root2合并到Root1中的原因
        S[Root1] += S[Root2];       // 累加节点个数
        S[Root2] = Root1;
    }else{
        S[Root2] += S[Root1];
        S[Root1] = Root2;
    }
    return 1;
}

void debug(){
    for(int i=0;i<MAXSIZE;i++){
        printf("%d ",UFSets[i]);
    }
    puts("");
}

int main(){
    InitUFSets(UFSets);
    int arr[100] = {0,1,2,3,4,5,6,7,8,9};
    for(int i=0;i<=10;i++){
        UnionElem(UFSets,arr[i*2],arr[i*2+1]);
        // 0 -- 1
        // 2 -- 3
        // 4 -- 5
        // 6 -- 7
        // 8 -- 9
    }
    UnionElem(UFSets,1,3);
    UnionElem(UFSets,5,7);
    // 0 -- 1
    // 2 -- 3
    // 4 -- 5
    // 6 -- 7
    // 8 -- 9
    // 0 -- 2
    // 4 -- 6

    UnionElem(UFSets,1,6);
    UnionElem(UFSets,2,7);
    // debug();



    return 0;
}

 

 

标签:return,idx,--,查集,len,int,IsEmpty,二叉树,TreeNode
From: https://www.cnblogs.com/lordtianqiyi/p/17610744.html

相关文章

  • spring-cron定时任务【@Scheduled(cron = “* * * * * *“)】
    1https://blog.csdn.net/HD243608836/article/details/1268862480010,14,16**?每天上午10点,下午2点,4点00/309-17**?朝九晚五工作时间内每半小时0012?*WED表示每个星期三中午12点"0012**?"每天中午12点触发"01510?**"每天上午10:15触发......
  • Oracle批量删除表
    数量小:生成删除表的语句,复制出删表语句,执行删除即可SELECT'DROPTABLE'||TABLE_NAME||';'FROMUSER_TABLESWHERETABLE_NAMELIKE'HR_TEMPTABLE__%';查询所有匹配上的表select*fromUSER_TABLESWHERETABLE_NAMELIKE'HR_TEMPTABLE__%';数量大:批量删除匹配......
  • 计讯物联3.0智慧灯杆网关TG473,创造智慧城市“数智”美好
    基于5G、物联网、智能传感、大数据、人工智能等新兴技术趋向于成熟,我国智慧城市规模发展迅速,并得到广泛的实施应用。除了技术层面,政策扶持对于智慧城市的建设也具有重大意义。今年的政府工作报告明确指出,要建设数字信息基础设施,推进5G规模化应用,促进产业数字化转型,发展智慧城市。......
  • 2023.8.7
    学习java中的类面向对象与面向过程面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做。面向对象:强调具备了功能的对象,以类/对象为最小单位类与对象的关系类:对一类事物的描述,是抽象的、概念上的定义对象:是实际存在的该类事物的每个个体,因而也称为实例(instance)面向对象......
  • 2023.8.6
    学习java中的类面向对象与面向过程面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做。面向对象:强调具备了功能的对象,以类/对象为最小单位类与对象的关系类:对一类事物的描述,是抽象的、概念上的定义对象:是实际存在的该类事物的每个个体,因而也称为实例(instance)面向对象......
  • 事件对象
                     ......
  • Mitsubishi 三菱FXPLC学习之子程序调用与循环
    上次,我们学习了程序流程转移中的条件跳转CJ,这次,我们接着向子程序调用CALL和FOR循环发起进攻吧!显然,子程序调用CALL和FOR循环和条件跳转CJ一样,都是PLC程序中用于流程转移的,所以,上次所学的程序区、主程序结束指令FEND等知识点可不要丢哟~在这里我也不再赘述了,这是为了给读者......
  • springcloud 整合sentinel
    一、参考官网:Sentinel·alibaba/spring-cloud-alibabaWiki·GitHub1.搭建sentinelDashborad     1.下载jar包: Releases·alibaba/Sentinel(github.com)     2.启动:java-Dserver.port=8080-Dcsp.sentinel.dashboard.server=localhost:8080-......
  • MQTT介绍
    一、MQTT简介《MQTT协议规范中文版》一书中对MQTT(MessageQueuingTelemetryTransport,消息队列遥测传输)进行了描述:MQTT是一种基于客户端服务端架构的发布/订阅模式的消息传输协议。它的设计思想是轻巧、开放、简单、规范,易于实现。这些特点使得它对很多场景来说都是很好......
  • python实战手册(1)
    目录编码声明换行标识符编码声明Python脚本第一或第二行的注释匹配正则表达式coding[=:]\s*([-\w.]+)时,则该注释为源代码的编码声明;这个表达式的第一组指定了源码文件的编码。编码声明必须独占一行,在第二行时,则第一行必须也是注释。编码表达式的形式如下:#-*-coding:<enc......