【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 =
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;
}

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

时间: 2024-10-23 13:03:07

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

数据结构课程设计题目四_二叉树

本文出自:http://blog.csdn.net/svitter 题目4:二叉树 给出一颗无线的二叉树.树的每一个结点用一整数对标识.二叉树构造如下 树根被标识为(1, 1): 如果一个结点被标识为(a, b), 则其左孩子被标识为(a+b,b),右孩子被标识为(a, a+b).现在给出某一结点(a, b),求树根到该结点的最短路径,并且同时求出从树根出发向左走和向右走的次数.建议完成人数1人. 注:此处使用了STL_stack库函数,是不允许的,我图方便. //===============

二叉树的非递归遍历C语言实现

腾讯面试中被问到二叉树的非递归遍历实现,当时记得不太清楚,回来专门复习了非递归的实现,整理代码如下: //采用二叉链表存储方式的二叉树,非递归中序遍历C语言实现代码 #include<stdio.h> #include <malloc.h> //函数结果状态代码 #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 //Status是

linux菜鸟学习(四)--目录结构

目录结构: 对于每一个Linux学习者来说,了解Linux文件系统的目录结构,是学好Linux的至关重要的一步.,深入了解linux文件目录结构的标准和每个目录的详细功能,对于我们用好linux系统只管重要,下面我们就开始了解一下linux目录结构的相关知识. 当在使用Linux的时候,如果您通过ls –l / 就会发现,在/下包涵很多的目录,比如etc.usr.var.bin ... ... 等目录,而在这些目录中,我们进去看看,发现也有很多的目录或文件.文件系统在Linux下看上去就象树形结

R语言基础知识学习(四):R中的画图函数--plot()函数

plot()函数是R中基本的画x-y两个变量的函数,其用法如下为:plot(x, y, ...) 例如:首先我用runif()函数产生了两列随机数:x1,y1,然后用plot()函数直接画图: > x1 <- round(runif(20,min = 0 ,max = 100))> x1 [1] 90 84 86 86 28 43 86 76 90 76 14 62 40 52 87 57 88 17[19] 10 27> y1 <- round(runif(20,min =

&lt;数据结构基础学习&gt;(四)链表

哎喂,别急着看啊,我还没有编辑好就误点发布了,今天晚上开完会回去就整理好,第二天回来看啊! 一.链表 动态数组.栈.队列底层都是依托静态数组实现的,靠resize来解决固定容量问题. 链表是真正的动态数据结构,是一种最简单的一种动态数据结构. 更深入的理解引用(或者指针). 更深入的理解递归. 辅助成其他数据结构. 二.链表 Linked list 数据存储在“节点”(Node)中 class Node{ E e; Node next; } 最后一个节点nxet=null 优点:真正的动态,不需

数据结构和算法学习六,之非递归排序

http://blog.csdn.net/feixiaoxing/article/details/6844826 在上面一篇博客当中,我们发现普通查找和排序查找的性能差别很大.作为一个100万的数据,如果使用普通的查找方法,那么每一个数据查找平均下来就要几十万次,那么二分法的查找呢,20多次就可以搞定.这中间的差别是非常明显的.既然排序有这么好的效果,那么这篇博客中,我们就对排序算做一个总结. 按照我个人的理解,排序可以分为两种:一种是非递归排序,它主要按照非递归的方法对数据进行排序,也就是说主

数据结构复习之二叉树的非递归先序,中序,后序遍历

#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<stack> using namespace std; struct Tree{ int x; Tree *lchild, *rchild; Tree(){ lchild = rchild = NULL; } }; typedef Tree* pT; void buildT(pT &

四:二叉树的镜像递归非递归求解

先序遍历树的每个结点,若遍历到的结点有子结点,则交换它的两个子结点. 1. 递归求解: voidMirroRecursively(BinaryTreeNode *pNode) { if(NULL == pNode) return; if(NULL == pNode->Left && NULL== pNode->Right) return; BinaryTreeNode *pTemp =pNode->Left; pNode->Left = pNode->Righ

二叉树学习之非递归遍历

二叉树递归遍历可谓是学过数据结构的同仁都能想一下就能写出来,但在应聘过程我们常常遇到的是写出一个二叉树非递归遍历函数,接着上篇文章写二叉树的非递归遍历,先难后易,一步一步的来. 先上代码: #include "binarytree.h" #include <stack> #include <queue> #ifndef RECU #warning("RECU is not defined") /** *前序遍历(根左右) * *1.当前节点为