首页 > 代码库 > 【C语言】【数据结构】菜鸟学习日志(四) 用二叉树实现非递归排序

【C语言】【数据结构】菜鸟学习日志(四) 用二叉树实现非递归排序

  唉,由于要备战考研,这篇博文可能是我这一年最后一次更新啦!

  其实断断续续的也没有写很多,而且大多都是很初级、很简单的东西,没有和大家分享什么高阶的东西。这也正应了我们《菜鸟学习日志》的标题嘛!

  不过说回来我还是很喜欢写博文的。一方面总结学到的知识,以后也可以自己看看别做了就忘了;另一方面,写博文也让我在学习的过程中更加认真,以免分享了错误的知识。

  写的东西好不好呢是一说,好像有一些点击量,不过看的人估计也不多。只是我还算乐在其中吧!

  大学生活说到底过得有点浪了,导致我苦逼地走向了考研的不归路……

 

  这次分享的博文也没什么高深的东西。今年和我一起选修了C语言的同学一看就明白为什么我要写这个了~

  反正很简单,我也不多解释了了,直接上代码。代码中已经给出了详细的注释,全是干货。

  这个代码算是写的比较健壮一些了,如果你觉得太麻烦也可以精简掉一些部分。

  另外,如果有什么不明白或者可以改进的地方,都可以给我留言!

  更多的博文,我们明年见吧!:)

-------------------------------------------

/*
binary_tree.c
将给定文件中的数据按照中序由小到大的顺序在二叉树中排序,再写入到文件中
这个程序采用非递归的算法(老师要求)
假设源文件和目标文件是两个不同的文件
假设文件中的数据为整型数
假设数据之间用空格符隔开
假设没有重复的数据
*/
#include <stdio.h>
#include <stdlib.h>
#define SFILE "/home/arcane/C_learning/binary_tree/num_1"    //源文件
#define OFILE "/home/arcane/C_learning/binary_tree/num_2"    //目标文件
#define MAXNODES 50                        //栈能存放的最大节点数

//定义了二叉树节点的结构体
struct node
{
    int data;
    struct node *plc;
    struct node *prc;
};
//用于遍历时存放节点的栈(数组)
struct node *nodes[MAXNODES];
//记录栈中节点的个数
int count = 0;
//用于创建节点
struct node *createNode(int data);
//根据值的大小在二叉树中插入节点
struct node *addNode(int value, struct node *pn);
//栈操作,压栈
int push(struct node *pn);
//栈操作,出栈
struct node *pop();

int main(void)
{
    FILE *fp;            //文件指针
    struct node *proot = NULL;    //指向根节点的指针
    struct node *pn;        //指向任意节点的指针
    struct node *p;            //用于辅助释放分配的空间
    char ch;            //记录从文件中读取的字符
    int num = 0;            //计算和记录从文件中读出的数字
    char s[10];            //用于将num转换为字符串
    int k=0;

    //把数据按顺序读入二叉树
    //打开文件
    if((fp = fopen(SFILE, "r")) == NULL)
    {
        printf("文件打开失败!\n");
        exit(1);
    }
    //读取数字并建立二叉树
    while ((ch = getc(fp)) != EOF)
    {
        if (ch == ‘ ‘)
        {
            if (proot == NULL)
                proot = createNode(num);
            else
                addNode(num,proot);
                
            num = 0;
        }
        else
            num = num * 10 + (ch - ‘0‘);    //字符是一个一个读入的,这里计算了被空格隔开的单个数字
    }
    //关闭文件
    fclose(fp);              


    //将二叉树按中序写入文件,顺便释放给树分配的空间
    //打开目标文件
    if((fp = fopen(OFILE, "w")) == NULL)
    {
        printf("文件打开失败!\n");
        exit(1);
    }

    //用循环而非递归的中序遍历,其中用到了栈
    pn = proot;
    while(1)
    {
        if(pn->plc != NULL)        //左子树存在
        {
            if(push(pn) == 1)
            {
                printf("栈溢出!\n");
                exit(1);
            }
            pn = pn->plc;
        }
        else                //左子树不存在
        {
            //把节点的值转换成字符串,并写入文件中
            sprintf(s, "%d", pn->data);
            fputs(s,fp);
                    
            
            if(pn->prc != NULL)    //右子树存在
            {
                putc(‘ ‘, fp);
                p = pn;        //中序遍历,当开始考虑右子树前,这个节点的信息已经写入文件了,所以可以释放了
                pn = pn->prc;
                free(p);
                k++;
            }
            else            //右子树不存在
            {
                free(pn);    //左右子树都不存在,这个节点可以释放了
                k++;
                if((pn = pop()) != NULL)
                {
                    putc(‘ ‘, fp);
                    pn->plc = NULL;
                }
                else
                    break;
            }
        }
    }
    //关闭目标文件
    fclose(fp);

    return 0;
}

/*
创建一个节点
其值为 value,左右节点为 NULL
*/
struct node *createNode(int value)
{
    struct node *pn = (struct node *)malloc(sizeof(struct node));
    pn->data = http://www.mamicode.com/value;
    pn->plc = pn->prc = NULL;

    return pn;
}

/*
向给定的二叉树中插入一个值为 value 的节点
规则是按中序由小到大的顺序
*/
struct node *addNode(int value, struct node *pn)
{
    struct node *p = pn;

    //利用循环而非递归的插入
    while(1)
    {
        if(p == NULL)        //二叉树不存在
            return createNode(value);

        if(value < p->data)    //属于二叉树的左子树
        {
            if(p->plc == NULL)
            {
                p->plc = createNode(value);
                return p->plc;
            }
            else
            {
                p = p->plc;
            }
        }
        else            //属于二叉树的右子树
        {
            if(p->prc == NULL)
            {
                p->prc = createNode(value);
                return p->prc;
            }
            else
            {
                p = p->prc;
            }
        }
    }
}

/*
压栈操作
成功返回0,失败返回1
*/
int push(struct node *pn)
{
    if(count == (MAXNODES - 1))
        return 1;

    nodes[count] = pn;
    count++;
    return 0;
}

/*
出栈操作
成功返回节点指针,失败返回NULL
*/
struct node *pop()
{
    if(count > 0)
        return nodes[--count];

    return NULL;
}