#include#include //iomanip格式控制库 using namespace std; typedef char eleData; //eleData定义数据类型 //作者:一贰柒一肆 //内容:树的构建、中序非递归遍历、中序线索树、中序线索遍历 //与书本略有不同,可以用作参考 static string data="abc##d##ef##g##"; //data存储数据 static int index=0; //index用来检索数据 typedef enum flog{link,node}childFlog; //childFlog结点孩子标记,link代表线索,node代表结点 typedef struct node{ eleData treeData; //treeData树存储的数据类型 node* leftChild; //leftChild树的左孩子 node* rightChild; //rightChild树的右孩子 childFlog left; //left左孩子标记 childFlog right; //right有孩子标记 }*treePre,treeNode; //treePre树的指针-------treeNode树的结点 void creatBiTree(treePre &T) //creatBiTree创建二叉树C/C++存在指针变量、传递结构体与对象时要采用引用 { if(index==data.length()) //data内的数据检索完成,不再执行后续步骤 { return; } if(data[index]=='#') //遇到#表示没有数据是空结点index++继续读下一位 { index++; return; } T=(treePre)malloc(sizeof(treeNode)); //创建结点空间 T->left=T->right=node; //初始化左右孩子标记域为结点 T->leftChild=T->rightChild=NULL; //初始化左右孩子指针域为NULL T->treeData=data[index++]; //初始化当前结点数据域为data[index],之后index++读后续数据 creatBiTree(T->leftChild); //创建左孩子 creatBiTree(T->rightChild); //创建右孩子 } void coutTreeMid(treePre T) //普通树中序非递归遍历 { treePre sk[data.length()]; //设置栈,栈容量是数据长度 int top=-1; //仅使用栈顶,初值设为-1表示栈空 while(T||top!=-1) //T代表访问的结点,top表示栈是否为空 { if(T) //如果结点存在 { sk[++top]=T; //结点入栈 T=T->leftChild; //结点向左孩子下移 } else //否则就是结点不存在的时候,该不存在结点为栈顶的左孩子 { cout< treeData; //先输出栈顶的数据,栈顶是该不存在结点的父结点--->对该父结点中序遍历:左子树为空、就要先输出数据、再检查右子树 T=sk[top--]->rightChild; //top--先检查右子树,再把该父结点退栈 } } } void creatLinkBiTree(treePre &T,treePre &pre) //创造中序线索二叉树 { if(!T) return; //如果结点不存在,直接回复、不进行后续操作 creatLinkBiTree(T->leftChild,pre); //先线索化左子树 if(!T->leftChild) //如果该结点左孩子不存在 { T->left=link; //把左孩子标志域设置为线索link T->leftChild=pre; //左孩子指针域指向前驱pre } if(!pre->rightChild) //前驱结点若无右孩子 { pre->right=link; //把右孩子标志域设置为线索link pre->rightChild=T; //右孩子指针域指向后继T } pre=T; //当前结点已经线索化,前驱要改变,变为当前结点 creatLinkBiTree(T->rightChild,pre); //开始线索化右孩子 } static void lookForNext(treePre &T,treePre treeHead) //寻找下一个结点,多次使用设为静态 { if(T->right==link) //如果当前结点的右标记域是线索 { T=T->rightChild; //则直接记录当前节点的右孩子即可 } else //如果当前结点的右标记是结点 { T=T->rightChild; //则要在右子树寻找后继 while(T!=treeHead&&T->left==node) //当T记录的不是头结点而且左孩子是结点时 { T=T->leftChild; //T就要向左孩子方向下移动 } //结束时T的左孩子不是结点而是指向了前驱,T就是前驱的后继 } } void coutLinkTree(treePre treeHead) //线索树的遍历 { treePre T=treeHead->rightChild; //T储存中序遍历第一个元素的位置 while(T!=treeHead) //当T不指向头结点时就继续循环,因为中序遍历最后一个元素的后继是头结点 { cout< treeData; //输出当前数据 lookForNext(T,treeHead); //找到下一个数据用T记录 } } treePre coutMidFirst(treePre T) //找到中序遍历的第一个数据 { while(T->leftChild) //第一个左孩子为空的结点就是中序遍历的第一个结点 { T=T->leftChild; //指针沿左孩子方向向下移动 } return T; //循环结束时就是第一个左孩子为空的结点,将该结点回复,因为该结点就是中序遍历的第一个结点 } int main() { treePre tree; //树根 cout<<"t***创造二叉树***"< left=node; //初始化左孩子标记域为结点 treeHead->right=link; //初始化右孩子标记域为线索 treeHead->leftChild=tree; //初始化左孩子指针域记录根结点 treeHead->rightChild=coutMidFirst(tree); //初始化右线索指向中序遍历的第一个结点 treePre pre=treeHead; //设置前驱,初始指向头节点 creatLinkBiTree(tree,pre); //调用函数创建线索二叉树 pre->rightChild=treeHead; //最后一个结点的后继指向头结点 cout<<"t***线索化成功***"< 直接上代码,大家看看不懂可以留言--有空就回复



