先序遍历
中序遍历
后序遍历
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
typedef struct BitNode{
int data;
struct BitNode *lchild, *rchild;
}BitNode;
typedef struct Node{
BitNode* data;
struct Node *next;
}Node,*Stack;
typedef struct LinkStack{
Node* top; //栈顶指针
int count; //元素个数
}LinkStack;
LinkStack InitStack(){
LinkStack stack;
stack.top = NULL;
stack.count = 0;
return stack;
}
void Push(LinkStack* stack,BitNode* x){
Node* s;
s = (Node*)malloc(sizeof(Node));
s->next = stack->top;
s->data = x;
stack->top = s;
stack->count++;
}
void Pop(LinkStack* stack){
Node* s;
s = stack->top;
stack->top = stack->top->next;
free(s);
stack->count--;
}
int isEmpty(LinkStack stack)
{
if (stack.count == 0)
{
return TRUE;
}
else
return FALSE;
}
//递归创建一棵二叉树
BitNode* Create_BitTree(){
int x;
scanf("%d",&x);
BitNode* node = NULL;
if(x != 999){
node = (BitNode*)malloc(sizeof(BitNode));
node->data = x;
node->lchild = Create_BitTree();
node->rchild = Create_BitTree();
}
return node;
}
//非递归前序遍历
void Preorder1(BitNode* T){
LinkStack S = InitStack(); //初始化一个栈
BitNode* p = T; //创造一个指向二叉树根的指针
while (p!=NULL||isEmpty(S)==0) { //只有当二叉树不为空或栈不为空时才会开始
while (p!=NULL) { //当二叉树不为空时
Push(&S,p); //将现在访问的结点
printf("%d\n", p->data); //输出现在正在访问的结点,相当于已经遍历过了
p = p->lchild; //因为是先序遍历,现在转到其结点的左孩子
} //循环一波直到最左孩子
if(isEmpty(S)==0){ //现在栈不为空,需要把其中存储元素的右结点弄出来
p = S.top->data; //获得现在的栈顶元素,也就是最左下子树根结点
Pop(&S); //栈元素-1
p = p->rchild; //现在获得最左下子树根结点的右孩子
}
}
}
//非递归中序遍历,与前序遍历类似,问题不大
void Inorder1(BitNode* T){
LinkStack S = InitStack();
BitNode* p = T;
while (p!=NULL||isEmpty(S)==0) {
while (p!=NULL) {
Push(&S,p);
p = p->lchild;
}
if(isEmpty(S)==0){
p = S.top->data;
Pop(&S);
printf("%d\n", p->data);
p = p->rchild;
}
}
}
//非递归后序遍历,与前中序遍历都不太一样
void Postorder1(BitNode* T){
LinkStack S = InitStack(); //初始化栈
BitNode* pCur = T; //当前访问节点的指针
BitNode* pLastVisit = NULL; //当前访问结点的上一个结点的指针
while (pCur!=NULL) { //只要当前的访问结点不为空,循环
Push(&S,pCur); //将当前结点入栈
pCur = pCur->lchild; //获得当前结点的左孩子
}
while (isEmpty(S)==0) { //只要栈不为空,循环
pCur = S.top->data; //从栈中获得当前结点
Pop(&S); //获取后元素出栈
if(pCur->rchild==NULL||pCur->rchild==pLastVisit){ //如果当前结点右孩子为空或等于当前结点的上一个访问结点
printf("%d\n",pCur->data); //输出
pLastVisit = pCur; //上一个访问结点变为现在输出过的结点
}
else{ //这种情况就是遇到子树根结点了
Push(&S,pCur); //将当前结点重新入栈
pCur = pCur->rchild; //当前结点指针指向其右孩子
while (pCur!=NULL) {
Push(&S,pCur); //将当前结点入栈
pCur = pCur->lchild; //获得当前结点的左孩子
}
}
}
}
//递归前序遍历
void Preorder(BitNode* T){
if(T != NULL){
printf("%d\n", T->data);
Preorder(T->lchild);
Preorder(T->rchild);
}
}
//递归中序遍历
void Inorder(BitNode* T){
if(T != NULL){
Inorder(T->lchild);
printf("%d\n", T->data);
Inorder(T->rchild);
}
}
//递归后序遍历
void Postorder(BitNode* T){
if(T != NULL){
Postorder(T->lchild);
printf("%d\n", T->data);
Postorder(T->rchild);
}
}
int main(int argc, char const *argv[]) {
BitNode* T = Create_BitTree();
Preorder(T);
Preorder1(T);
Inorder(T);
Inorder1(T);
Postorder(T);
Postorder1(T);
return 0;
}
层次遍历(利用队列,和BFS的方法很像,略)
线索二叉树
#include <stdio.h>
#include <stdlib.h>
#define TElemType char//宏定义,结点中数据域的类型
//枚举,Link为0,Thread为1
typedef enum {
Link,
Thread
}PointerTag;
//结点结构构造
typedef struct BiThrNode{
TElemType data;//数据域
struct BiThrNode* lchild,*rchild;//左孩子,右孩子指针域
PointerTag Ltag,Rtag;//标志域,枚举类型
}BiThrNode,*BiThrTree;
BiThrTree pre=NULL;
//采用前序初始化二叉树
//中序和后序只需改变赋值语句的位置即可
void CreateTree(BiThrTree * tree){
char data;
scanf("%c",&data);
if (data!='#')
{
if (!((*tree)=(BiThrNode*)malloc(sizeof(BiThrNode))))
{
printf("申请结点空间失败");
return;
}
else
{
(*tree)->data=data;//采用前序遍历方式初始化二叉树
CreateTree(&((*tree)->lchild));//初始化左子树
CreateTree(&((*tree)->rchild));//初始化右子树
}
}
else
{
*tree=NULL;
}
}
//中序对二叉树进行线索化
void InThreading(BiThrTree p){
//如果当前结点存在
if (p)
{
InThreading(p->lchild);//递归当前结点的左子树,进行线索化
//如果当前结点没有左孩子,左标志位设为1,左指针域指向上一结点 pre
if (!p->lchild) {
p->Ltag=Thread;
p->lchild=pre;
}
//如果 pre 没有右孩子,右标志位设为 1,右指针域指向当前结点。
if (pre&&!pre->rchild) {
pre->Rtag=Thread;
pre->rchild=p;
}
pre=p;//pre指向当前结点
InThreading(p->rchild);//递归右子树进行线索化
}
}
//中序遍历线索二叉树
void InOrderThraverse_Thr(BiThrTree p)
{
while(p)
{
//一直找左孩子,最后一个为中序序列中排第一的
while(p->Ltag == Link){
p = p->lchild;
}
printf("%c ", p->data); //操作结点数据
//当结点右标志位为1时,直接找到其后继结点
while(p->Rtag == Thread && p->rchild !=NULL)
{
p = p->rchild;
printf("%c ", p->data);
}
//否则,按照中序遍历的规律,找其右子树中最左下的结点,也就是继续循环遍历
p = p->rchild;
}
}
int main() {
BiThrTree t;
printf("输入前序二叉树:\n");
CreateTree(&t);
InThreading(t);
printf("输出中序序列:\n");
InOrderThraverse_Thr(t);
return 0;
}
双亲表示法
#include<stdio.h>
#include<stdlib.h>
#define MAX_SIZE 20
typedef char ElemType;//宏定义树结构中数据类型
typedef struct Snode //结点结构
{
ElemType data;
int parent; //双亲位置域
}PNode;
typedef struct //树结构
{
PNode tnode[MAX_SIZE];
int n; //结点个数
}PTree;
PTree InitPNode(PTree tree)
{
int i,j;
char ch;
printf("请输出节点个数:\n");
scanf("%d",&(tree.n));
printf("请输入结点的值其双亲位于数组中的位置下标:\n");
for(i=0; i<tree.n; i++)
{
fflush(stdin);
scanf("%c %d",&ch,&j);
tree.tnode[i].data = ch;
tree.tnode[i].parent = j;
}
return tree;
}
void FindParent(PTree tree)
{
char a;
int isfind = 0;
printf("请输入要查询的结点值:\n");
fflush(stdin);
scanf("%c",&a);
for(int i =0;i<tree.n;i++){
if(tree.tnode[i].data == a){
isfind=1;
int ad=tree.tnode[i].parent;
printf("%c的父节点为 %c,存储位置下标为 %d",a,tree.tnode[ad].data,ad);
break;
}
}
if(isfind == 0){
printf("树中无此节点");
}
}
int main()
{
PTree tree;
tree = InitPNode(tree);
FindParent(tree);
return 0;
}
孩子表示法
#include<stdio.h>
#include<stdlib.h>
#define MAX_SIZE 20
#define TElemType char
//孩子表示法
typedef struct CTNode{
int child;//链表中每个结点存储的不是数据本身,而是数据在数组中存储的位置下标
struct CTNode * next;
}ChildPtr;
typedef struct {
TElemType data;//结点的数据类型
ChildPtr* firstchild;//孩子链表的头指针
}CTBox;
typedef struct{
CTBox nodes[MAX_SIZE];//存储结点的数组
int n,r;//结点数量和树根的位置
}CTree;
//孩子表示法存储普通树
CTree initTree(CTree tree){
printf("输入节点数量:\n");
scanf("%d",&(tree.n));
for(int i=0;i<tree.n;i++){
printf("输入第 %d 个节点的值:\n",i+1);
fflush(stdin);
scanf("%c",&(tree.nodes[i].data));
tree.nodes[i].firstchild=(ChildPtr*)malloc(sizeof(ChildPtr));
tree.nodes[i].firstchild->next=NULL;
printf("输入节点 %c 的孩子节点数量:\n",tree.nodes[i].data);
int Num;
scanf("%d",&Num);
if(Num!=0){
ChildPtr * p = tree.nodes[i].firstchild;
for(int j = 0 ;j<Num;j++){
ChildPtr * newEle=(ChildPtr*)malloc(sizeof(ChildPtr));
newEle->next=NULL;
printf("输入第 %d 个孩子节点在顺序表中的位置",j+1);
scanf("%d",&(newEle->child));
p->next= newEle;
p=p->next;
}
}
}
return tree;
}
void findKids(CTree tree,char a){
int hasKids=0;
for(int i=0;i<tree.n;i++){
if(tree.nodes[i].data==a){
ChildPtr * p=tree.nodes[i].firstchild->next;
while(p){
hasKids = 1;
printf("%c ",tree.nodes[p->child].data);
p=p->next;
}
break;
}
}
if(hasKids==0){
printf("此节点为叶子节点");
}
}
int main()
{
CTree tree;
tree = initTree(tree);
//默认数根节点位于数组notes[0]处
tree.r=0;
printf("找出节点 F 的所有孩子节点:");
findKids(tree,'F');
return 0;
}

孩子兄弟表示法
#define ElemType char
typedef struct CSNode{
ElemType data;
struct CSNode * firstchild,*nextsibling;
}CSNode,*CSTree;

先根遍历:若树非空,先访问根结点,再按从左到右的顺序遍历根结点的每棵子树,访问顺序与这棵树相应的二叉树的先序遍历相同
后根遍历:若树非空,先访问根结点,再按从左到右的顺序遍历根结点的每棵子树,访问顺序与这棵树相应的二叉树的中序遍历相同
中根遍历:没有的事哈,你怎么确定哪个是中哈哈哈
先序遍历森林:就正常的
后序遍历森林:就正常的
中序遍历森林:只有二叉树森林才有中序遍历与完整二叉树中序遍历对应
王道描述坑爹啊
Union(S,root1,root2):表示把集合S中的自己和root2并入子集合root1中。要求root1和root2互不相交,否则不执行合并操作
Find(S,x):查找集合S中单元素x所在的子集合,并且返回该子集合的名字
Initial(S):将集合S中的每个元素都初始化为只有一个单元素的子集合
通常用树的双亲表示作为并查集的存储结构,每个子集合以一棵树表示
所以子集合的树构成表示全集合的森林
数组元素下标表示元素名,根结点下标表示子集合名,根结点双亲结点表示负数
#define SIZE 100
int UFSets[SiZE]; //并查集所使用的数组,双亲指针数组
void Initial(int S[]){ //每个自成单元集合
for(int i=0;i<size;i++){
S[i] = -1;
}
}
int Find(int S[], int x){ //Find操作
while(S[x] >= 0){ //不能是根结点
x = S[x];
}
return x;
}
void Union(int S[], int root1, int root2){
S[root2] = root1;
}
二叉排序树的定义(可以为空):
二叉排序树的查找
//非递归形式的查找算法
BSTNode* BST_Search(BiTree T, int key, BSTNode* p){
p = NULL; //p指向被查找结点的双亲,用于插入和查找操作
while(T != NULL && key != T->data){
p = T;
if(key < T->data){
T = T->lchild;
}else{
T = T->rchild;
}
}
return T;
}
二叉树的插入:动态集合,并不是一次生成的,需要一步步插入
int BST_Insert(BiTree T, int k){
//在二叉排序树中插入一个关键字为k的结点
if(T == NULL){ //原树为空,新插入的记录为根结点
T = (BiTree)malloc(sizeof(BSTNode));
T->key = k;
T->lchild = T->rchild = NULL;
return 1;
}
else if(k == T->key){ //树中存在相同的关键字
return 0;
}
else if(k < T->key){
return BST_Insert(T->lchild, k); //插入T的左子树
}
else{
return BST_Insert(T->rchild, k); //插入T的右子树
}
}
二叉树的构造:依次输入数据,插入到二叉排序树中合适的位置
void Creat_BST(BiTree T, int str[],int n){
//用关键字数组建立一个二叉排序树
T = NULL;
int i=0;
while(i < n){
BST_Insert(T, str[i]);
i++;
}
}
二叉树排序树的删除:对于平衡二叉树也有启发作用
二叉排序树的查找效率分析
Comments
😅 Commenting is disabled on this post.