算法练习

(01)-把二元查找树转变成排序的双向链表
题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。

比如将二元查找树
10
/ \
6 14
/ \ / \
4 8 12 16
转换成双向链表
4=6=8=10=12=14=16。

思路一:当我们到达某一结点准备调整以该结点为根结点的子树时,先调整其左子树将左子树转换成一个排好序的左子链表,再调整其右子树转换右子链表。最近链接左子链表的最右结点(左子树的最大结点)、当前结点和右子链表的最左结点(右子树的最小结点)。从树的根结点开始递归调整所有结点。
思路二:我们可以中序遍历整棵树。按照这个方式遍历树,比较小的结点先访问。如果我们每访问一个结点,假设之前访问过的结点已经调整成一个排序双向链表,我们再把调整当前结点的指针将其链接到链表的末尾。当所有结点都访问过之后,整棵树也就转换成一个排序双向链表了。

思路一对应的代码:

BinaryTreeToList.c

#include <stdio.h>
#include <stdbool.h>
typedef struct Node
{
    int m_value;
    struct Node *m_pLeft;
    struct Node *m_pRight;
}BSTreeNode;

//pNode is the head of sub-tree, asRight is whether pNode is the right child of its parent
//if asRight is true, return the least node in the sub-tree else return the biggest node in the sub-tree
BSTreeNode *ConvertNode(BSTreeNode *pNode, bool asRight)
{
    if(!pNode)
    {
        return NULL;
    }

    BSTreeNode *pLeft = NULL;
    BSTreeNode *pRight = NULL;

    if(pNode->m_pLeft)
    {
        pLeft = ConvertNode(pNode->m_pLeft, false);
    }

    if(pLeft)
    {
        pLeft->m_pRight = pNode;
        pNode->m_pLeft = pLeft;
    }

    if(pNode->m_pRight)
    {
        pRight = ConvertNode(pNode->m_pRight, true);
    }

    if(pRight)
    {
        pRight->m_pLeft = pNode;
        pNode->m_pRight = pRight;
    }

    BSTreeNode *pTemp = pNode;

    if(asRight)
    {
        while(pTemp->m_pLeft)
            pTemp = pTemp->m_pLeft;
    }else{
        while(pTemp->m_pRight)
            pTemp = pTemp->m_pRight;
    }

    return pTemp;

}    

BSTreeNode *Convert(BSTreeNode *pHeadOfTree)
{
    //As we want to return the head of double-link list
    //we should set second parameter as true
    return ConvertNode(pHeadOfTree, true);
}

void main()
{
    int i,j;
    BSTreeNode *s;
    BSTreeNode *node[7];
    for(i = 0; i <7; i++)
    {
        node[i] = (BSTreeNode *)malloc(sizeof(BSTreeNode));
    }
    node[0]->m_value = 10;
    node[1]->m_value = 6;
    node[2]->m_value = 14;
    node[3]->m_value = 4;
    node[4]->m_value = 8;
    node[5]->m_value = 12;
    node[6]->m_value = 16;

    node[0]->m_pLeft = node[1];
    node[0]->m_pRight = node[2];
    node[1]->m_pLeft = node[3];
    node[1]->m_pRight = node[4];
    node[2]->m_pLeft = node[5];
    node[2]->m_pRight = node[6];
    node[3]->m_pLeft = NULL;
    node[3]->m_pRight = NULL;
    node[4]->m_pLeft = NULL;
    node[4]->m_pRight = NULL;
    node[5]->m_pLeft = NULL;
    node[5]->m_pRight = NULL;
    node[6]->m_pLeft = NULL;
    node[6]->m_pRight = NULL;

    s = Convert(node[0]);
    printf("Last order List: ");
    for(j = 0; j <7; j++){
        printf("node[%d]=%d   ",j,s->m_value);
        s = s->m_pRight;
    }
}                 

appendix:
segmentation fault (core dumped) 调试(gdb调试)
http://blog.csdn.net/u011563434/article/details/51199912

写程序经常会遇到这样一个错误:segmentation fault (core dumped)。怎么去解决呢?
首先,就是要知道错误发生的地方。而Linux系统可以产生core文件,配合gdb就可以解决这个问题。
第一步,让系统在信号中断造成的错误时产生core文件
ulimit -c unlimited // 设置core大小为无限
ulimit unlimited //设置文件大小为无限
第二步,编译运行与原来的程序
gcc -o XXX XXX.c -g
./XXX
运行后, ls 发现多出来了core文件
第三步, 用gdb查看core文件
gdb XXX core
然后,输入bt,就会出现错误的位置。如下图
这里写图片描述
0就是错误的具体位置。具体错误可以从#3到#0来找。这里的错误是fseek第一个参数为0x0,也就是说,文件指针为NULL。再看代码,发现原来文件指针没有释放掉,所以在之后的访问同样文件时,发生了错误。
由此可见,这种调试的方法还是不错的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值