将二叉树按照螺旋顺序分层连接

本文介绍如何将二叉树转换为螺旋顺序的双链表,提供两种实现方式:一种允许使用额外空间,另一种则完全就地完成,不使用额外空间(除了递归调用栈)。详细讨论了每种方法的实现细节,并提供了具体代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Write a program to convert binary tree in to doubly linked list such that doubly linked list represents the spiral order of given tree using recursion, Inplace(no Extra Space except recursion memory stack)

given pointer to head of binary tree

1
/ \
2 3
/ \ / \
4 5 6 7

doubly linked list represent

head-> 1 2 3 7 6 5 4


最后的两个算法都是有错误的,以现在的两个算法为准:

如果使用额外空间,倒第二个算法,也是错误的,放入vec的顺序和从vec读取的顺序的周期有问题,不能螺旋打印。可以这样做,在连接每一层之前,先从左到右把节点的left和right放入vec中,然后在根据flag是从左到右还是从右到左把节点从vec中取出并用双链表连接,每一层flag取反:


struct node{
    int val;
    node *left;
    node *right;   
};

void append(node* &head, vector<node*>&vec, int beg, int end, bool flag ) {
    if (flag) {
        for (int i = beg; i <= end; ++i) {
            node* n = vec[i];
            n->right = NULL;
            head->right = n;
            n->left = head;
            head = n;
        }
    }
    else {
        for (int i = end; i >= beg; --i) {
            node* n = vec[i];
            n->right = NULL;
            head->right = n;
            n->left = head;
            head = n;
        }
    }
}

void push(vector<node*>& vec, int beg, int end) {
    for (int i = beg; i <= end; ++i) {
        node *n = vec[i];
        if (n->left) vec.push_back(n->left);
        if (n->right) vec.push_back(n->right);
    }
}

node* bitree2dlink(node *root) {
    if (!root) return NULL;
    vector<node*> vec;
    int beg = 0;
    int end = 0;
    vec.push_back(root);
    node head;
    head->left = NULL;
    head->right = NULL;
    node *pt = &head;
    bool flag = false;
    while(vec.size() > 0) {
        push(vec, beg, end);
        append(pt, beg, end, flag);
        flag = !flag;
        beg = end + 1;
        end = vec.size() - 1;
    }
    return pt->right;
}


如果不用额外空间,直接使用递归的做法是,根据每个节点所处的层高,通过递归查找把这一层的节点都连接起来。注意的是不能从高层节点向底层节点的方向,因为下次递归的时候必须用经过高层节点才能到达底层节点。从底层向高层一层一层的递归连接。当level=height时,连接的是最后一层,level=head-1,连接到第二层,level=0,就是连接的最高层的那个节点。要注意的是,把节点放入双向链表时是从头部添加的。

int height(node* root) {
    if (root == NULL) return 0;
    return max(height(root->left)+1, height(root->right) + 1);
}

void tree2link(node*pt, node* n, int level, bool flag) {
    if (n == NULL) return;
    if (level == 0) {
         n->right = pt->right;
         if (pt->right) pt->right->left = n;
         pt->right = n;
         n->left = pt;
    }
    if (level > 0) {
        if (flag) {
            tree2link(pt, n->left, level - 1, flag);
            tree2link(pt, n->right, level - 1, flag);
        }
        else {
            tree2link(pt, n->right, level - 1, flag);
            tree2link(pt, n->left, level - 1, flag);
        }
    }
}

node *recurBitree2dl(node *root) {
    if (!root) return NULL;
    node head;
    node* pt = &head;
    int h = height(root) - 1;
    bool flag = true;
    for (int i = h; i >= 0; --i) {
        tree2link(pt, root, i, flag);
        flag = ~flag; 
    }
}



////////////////////////////////////////////////////////////////////////////////////

以下的代码都有错误

如果允许用额外空间,题目相对比较简单

Node *tree2Link(Node *root) {
    if (root == NULL)
        return NULL;

    vector<Node *> vec;
    bool flag = true;
    vec.push_back(root);

    int beg = 0, end = 0;
    Node head;
    Node *t = &head;

    while (!vec.empty()) {
        if (flag) {
            int i = beg;
            for (;i< = end; ++i) {
                Node *tmp = vec[i];
                if (tmp->left)
                    vec.push_back(tmp->left);
                if (tmp->right)
                    vec.push_back(tmp->right);
                t->right = tmp;
                tmp->left = t;
                
                t = tmp;

            }

           
        }
        else {
            int i = end;
            for (; i >= beg; --i) {
                Node *tmp = vec[i];
                if (tmp->right)
                    vec.push_back(tmp->right);
                if (tmp->left)
                    vec.push_back(tmp->left);

                t->right = tmp;
                tmp->left = t;

                t = tmp;
            }


        }

        beg = end + 1;
        end = vec.size() - 1;

        flag = ~flag;
    }

    return head.right;

}



不用额外空间,在网上看到一种方法,复杂度比较高,但是思路不错。

先计算出数的高度,从最低层开始逐层连接。

struct node
{
    struct node *left;
    struct node *right;
    int data;

};

struct node *rslt;//Global structure pointer..it point to head of doubly linked list 


int height(struct node* head)
{

    if(head==NULL)
        return 0;

    if(head->left==NULL && head->right==NULL)
        return 0;

    int lh=height(head->left);
    int rh=height(head->right);

    return lh>rh?(lh+1):(rh+1);

}

struct node* appnd(struct node *a,struct node *b)
{
    if(a==NULL)return b;
    if(b==NULL)return a;

    struct node* result=a;
    while(a->left!=NULL)
        a=a->left;

    a->left=b;
    b->right=a;

    //b->left=NULL;


    return result;

}

void printGivenLevel(struct node* head,int level,int ltr)
{
    if(head==NULL)
        return;

    if(level==0)
    {
        appnd(rslt, head);
        rslt = head;
    }

    if(level>0)
    {

        if(ltr)
        {
            printGivenLevel(head->left,level-1,ltr);
            printGivenLevel(head->right,level-1,ltr);
        }
        else
        {
            printGivenLevel(head->right,level-1,ltr);
            printGivenLevel(head->left,level-1,ltr);

        }
    }

}

void printGivenOrder(struct node* head)
{

    int i=0;
    int ltr=0;

    for(i=height(head); i >= 0; i--)
    {

        printGivenLevel(head,i,ltr);
        ltr=~ltr;
    }

}

struct node* NewNode(int data)
{
    struct node* tmp=(struct node *)malloc(sizeof(struct node));
    tmp->data=data;
    tmp->left=NULL;
    tmp->right=NULL;
    return tmp;

}

void printList(struct node* node)
{
    struct node* current=node;
    while(current)
    {
        printf("%d ----> ",current->data);
        current=current->right;
    }


}

int main()
{
    struct node* start=NULL;

    start=NewNode(1);
    start->left=NewNode(2);
    start->right=NewNode(3);
    start->left->left=NewNode(4);
    start->left->right=NewNode(5);
    start->right->left=NewNode(6);
    start->right->right=NewNode(7);

    printGivenOrder(start);

    printList(rslt);

    return 0;

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值