本文谢绝转载,原文来自http://990487026.blog.51cto.com

树
数据结构与算法 3:二叉树,遍历,创建,释放,拷贝,求高度,面试,线索树二叉树的创建,关系建立二叉树的创建,关系建立2三叉链表法双亲链表:二叉树的遍历遍历的分析PPT计算二叉树中叶子节点的数目:使用全局变量计数器计算二叉树中叶子节点的数目:不使用全局变量计数器无论是先序遍历,中序遍历,后序遍历,求叶子的数字都不变;因为本质都是一样的,任何一个节点都会遍历3趟求二叉树的高度二叉树的拷贝:二叉树的遍历-中序遍历非递归算法`栈的非常经典案例二叉树的遍历-中序遍历非递归算法,STL代码实现利用C++ STL实现 顺序存储  泛型 API泛型编程的威力,指针搞起来二叉树的创建 #号方法面试题-画二叉树面试题-画二叉树2数据结构演示工具二叉树的非递归遍历,C语言基于栈API实现线索二叉树[很难]

二叉树的创建,关系建立

chunli@http://990487026.blog.51cto.com~/binary_tree$ cat main.c
//二叉链表#include <stdio.h>typedef struct BiTNode
{int data;struct BiTNode *lchild;struct BiTNode *rchild;
}BiTNode,*BiTree;//推导
//struct BiTNode
//{
//  int data;
//  struct BiTNode *lchild;
//  struct BiTNode *rchild;
//};
//typedef struct BiTNode  BiTNode;
//typedef struct BiTNode* BiTree;int main()
{//创建节点BiTNode t1;  t1.data = 1;BiTNode t2;    t1.data = 2;BiTNode t3;    t1.data = 3;BiTNode t4;    t1.data = 4;BiTNode t5;    t1.data = 5;//建立关系t1.lchild = &t2;t1.rchild = &t3;t2.lchild = &t4;t3.lchild = &t5;return 0;
}
chunli@http://990487026.blog.51cto.com~/binary_tree$ gcc main.c  && ./a.out
chunli@http://990487026.blog.51cto.com~/binary_tree$

2:二叉树的创建,关系建立

chunli@http://990487026.blog.51cto.com~/binary_tree$ cat main.c
//二叉链表
#include <stdio.h>
#include <stdlib.h>
typedef struct BiTNode
{int data;struct BiTNode *lchild;struct BiTNode *rchild;
}BiTNode,*BiTree;int main()
{BiTNode *p1;   p1 = (BiTNode*)malloc(sizeof(BiTNode));BiTNode *p2;    p2 = (BiTNode*)malloc(sizeof(BiTNode));BiTNode *p3;    p3 = (BiTNode*)malloc(sizeof(BiTNode));BiTNode *p4;    p4 = (BiTNode*)malloc(sizeof(BiTNode));BiTNode *p5;    p5 = (BiTNode*)malloc(sizeof(BiTNode));p1->data = 1;p2->data = 2;p3->data = 3;p4->data = 4;p5->data = 5;//建立关系p1->lchild = p2;p1->rchild = p3;p2->lchild = p4;p3->rchild = p5;return 0;
}
chunli@http://990487026.blog.51cto.com~/binary_tree$ gcc main.c  && ./a.out
chunli@http://990487026.blog.51cto.com~/binary_tree$


三叉链表法

//三叉链表
typedef struct TriTNode
{int data;//左右孩子指针struct TriTNode *lchild, *rchild;struct TriTNode *parent;
}TriTNode, *TriTree;

双亲链表:

//双亲链表
#define MAX_TREE_SIZE 100
typedef struct BPTNode
{int data;int parentPosition; //指向双亲的指针 //数组下标char LRTag; //左右孩子标志域
}BPTNode;typedef struct BPTree
{BPTNode nodes[100]; //因为节点之间是分散的,需要把节点存储到数组中int num_node;  //节点数目int root; //根结点的位置 //注意此域存储的是父亲节点在数组的下标
}BPTree;//用这个数据结构能表达出一颗树。。。能,怎么表达?不能why



程序:

chunli@http://990487026.blog.51cto.com~/binary_tree$ cat main.c
//二叉链表
#include <stdio.h>
#include <stdlib.h>
typedef struct BPNode
{int data;int parentPosition;char LRTag;
}BPTNode;typedef struct BPtree
{BPTNode nodes[100];int num_node;int root;
}BPTree;int main()
{BPTree tree;//节点属性数值//根节点tree.nodes[0].parentPosition = 10000;//定义10000为root节点,自己定//B节点tree.nodes[1].parentPosition = 0;//0号节点是老爹的tree.nodes[1].data = 'B';tree.nodes[1].LRTag  = 1;//C节点tree.nodes[2].parentPosition = 0;//0号节点是老爹的tree.nodes[3].data = 'C';tree.nodes[4].LRTag  = 2;return 0;
}
chunli@http://990487026.blog.51cto.com~/binary_tree$ gcc main.c  -Wall && ./a.out
main.c: In function ‘main’:
main.c:21:9: warning: variable ‘tree’ set but not used [-Wunused-but-set-variable]BPTree tree;^
chunli@http://990487026.blog.51cto.com~/binary_tree$

二叉树的遍历

chunli@http://990487026.blog.51cto.com~/binary_tree$ cat main.c
//树的遍历
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct BiTNode
{int data;struct BiTNode *lchild;struct BiTNode *rchild;
}BiTNode,*BiTree;void pre_Order(BiTNode * root) //先序遍历
{if(root == NULL){return ;}printf("%d ",root->data);pre_Order(root->lchild);//遍历左子树pre_Order(root->rchild);//遍历右子树
}void in_Order(BiTNode * root)  //中序遍历
{if(root == NULL){return ;}in_Order(root->lchild);//遍历左子树printf("%d ",root->data);in_Order(root->rchild);//遍历右子树
}void post_Order(BiTNode * root)    //后序遍历
{if(root == NULL){return ;}post_Order(root->lchild);//遍历左子树post_Order(root->rchild);//遍历右子树printf("%d ",root->data);
}
int main()
{//创建节点BiTNode t1;  memset(&t1,0,sizeof(BiTNode));  t1.data = 1;BiTNode t2;    memset(&t2,0,sizeof(BiTNode));  t2.data = 2;BiTNode t3;    memset(&t3,0,sizeof(BiTNode));  t3.data = 3;BiTNode t4;    memset(&t4,0,sizeof(BiTNode));  t4.data = 4;BiTNode t5;    memset(&t5,0,sizeof(BiTNode));  t5.data = 5;//建立关系t1.lchild = &t2;t1.rchild = &t3;t2.lchild = &t4;t3.lchild = &t5;//树的遍历pre_Order(&t1);        printf("    先序遍历\n");in_Order(&t1);       printf("    中序遍历\n");post_Order(&t1); printf("    后序遍历\n");return 0;
}
chunli@http://990487026.blog.51cto.com~/binary_tree$ gcc main.c   && ./a.out
1 2 4 3 5     先序遍历
4 2 1 5 3     中序遍历
4 2 5 3 1     后序遍历
chunli@http://990487026.blog.51cto.com~/binary_tree$

计算二叉树中叶子节点的数目:使用全局变量计数器

chunli@http://990487026.blog.51cto.com~/binary_tree$ cat main.c
//树的遍历
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct BiTNode
{int data;struct BiTNode *lchild;struct BiTNode *rchild;
}BiTNode,*BiTree;void pre_Order(BiTNode * root) //先序遍历
{if(root == NULL){return ;}printf("%d ",root->data);pre_Order(root->lchild);//遍历左子树pre_Order(root->rchild);//遍历右子树
}void in_Order(BiTNode * root)  //中序遍历
{if(root == NULL){return ;}in_Order(root->lchild);//遍历左子树printf("%d ",root->data);in_Order(root->rchild);//遍历右子树
}void post_Order(BiTNode * root)    //后序遍历
{if(root == NULL){return ;}post_Order(root->lchild);//遍历左子树post_Order(root->rchild);//遍历右子树printf("%d ",root->data);
}int  count_leaf(BiTNode * root)    //中序遍历
{static num = 0;if(root){if(!root->rchild && !root->rchild)//当左右孩子都为空,就是叶子节点{num++;}if(root->rchild){count_leaf(root->lchild);//遍历左子树}if(root->rchild){count_leaf(root->rchild);//遍历右子树}}return num;
}
int main()
{//创建节点BiTNode t1;  memset(&t1,0,sizeof(BiTNode));  t1.data = 1;BiTNode t2;    memset(&t2,0,sizeof(BiTNode));  t2.data = 2;BiTNode t3;    memset(&t3,0,sizeof(BiTNode));  t3.data = 3;BiTNode t4;    memset(&t4,0,sizeof(BiTNode));  t4.data = 4;BiTNode t5;    memset(&t5,0,sizeof(BiTNode));  t5.data = 5;//建立关系t1.lchild = &t2;t1.rchild = &t3;t2.lchild = &t4;t3.lchild = &t5;//树的遍历pre_Order(&t1);        printf("    先序遍历\n");in_Order(&t1);       printf("    中序遍历\n");post_Order(&t1); printf("    后序遍历\n");int num = count_leaf(&t1);printf("叶子节点的个数 %d\n",num);return 0;
}
chunli@http://990487026.blog.51cto.com~/binary_tree$ gcc main.c   && ./a.out
1 2 4 3 5     先序遍历
4 2 1 5 3     中序遍历
4 2 5 3 1     后序遍历
叶子节点的个数 2
chunli@http://990487026.blog.51cto.com~/binary_tree$

计算二叉树中叶子节点的数目:不使用全局变量计数器

chunli@http://990487026.blog.51cto.com~/binary_tree$ cat main.c
//树的遍历
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct BiTNode
{int data;struct BiTNode *lchild;struct BiTNode *rchild;
}BiTNode,*BiTree;void pre_Order(BiTNode * root) //先序遍历
{if(root == NULL){return ;}printf("%d ",root->data);pre_Order(root->lchild);//遍历左子树pre_Order(root->rchild);//遍历右子树
}void in_Order(BiTNode * root)  //中序遍历
{if(root == NULL){return ;}in_Order(root->lchild);//遍历左子树printf("%d ",root->data);in_Order(root->rchild);//遍历右子树
}void post_Order(BiTNode * root)    //后序遍历
{if(root == NULL){return ;}post_Order(root->lchild);//遍历左子树post_Order(root->rchild);//遍历右子树printf("%d ",root->data);
}void count_leaf(BiTNode * root,int * num)
{if(!root){return ;}if(!root->rchild && !root->rchild)//当左右孩子都为空{(*num)++;}if(root->lchild){count_leaf(root->lchild,num);//遍历左子树}if(root->rchild){count_leaf(root->rchild,num);//遍历右子树}return ;
}
int main()
{//创建节点BiTNode t1;  memset(&t1,0,sizeof(BiTNode));  t1.data = 1;BiTNode t2;    memset(&t2,0,sizeof(BiTNode));  t2.data = 2;BiTNode t3;    memset(&t3,0,sizeof(BiTNode));  t3.data = 3;BiTNode t4;    memset(&t4,0,sizeof(BiTNode));  t4.data = 4;BiTNode t5;    memset(&t5,0,sizeof(BiTNode));  t5.data = 5;//建立关系t1.lchild = &t2;t1.rchild = &t3;t2.lchild = &t4;t3.lchild = &t5;//树的遍历pre_Order(&t1);        printf("    先序遍历\n");in_Order(&t1);       printf("    中序遍历\n");post_Order(&t1); printf("    后序遍历\n");int num = 0;count_leaf(&t1,&num);   //解决多线程,资源竞争问题printf("叶子节点的个数 %d\n",num);return 0;
}
chunli@http://990487026.blog.51cto.com~/binary_tree$ gcc main.c  -Wall && ./a.out
1 2 4 3 5     先序遍历
4 2 1 5 3     中序遍历
4 2 5 3 1     后序遍历
叶子节点的个数 2
chunli@http://990487026.blog.51cto.com~/binary_tree$

无论是先序遍历,中序遍历,后序遍历,求叶子的数字都不变;因为本质都是一样的,任何一个节点都会遍历3趟

chunli@http://990487026.blog.51cto.com~/binary_tree$ cat main.c
//树的遍历
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct BiTNode
{int data;struct BiTNode *lchild;struct BiTNode *rchild;
}BiTNode,*BiTree;void count_leaf(BiTNode * root,int * num)  //求叶子的个数
{if(!root){return ;}if(root->lchild){count_leaf(root->lchild,num);//遍历左子树}if(!root->rchild && !root->rchild)//当左右孩子都为空{(*num)++;}if(root->rchild){count_leaf(root->rchild,num);//遍历右子树}return ;
}
int main()
{//创建节点BiTNode t1;  memset(&t1,0,sizeof(BiTNode));  t1.data = 1;BiTNode t2;    memset(&t2,0,sizeof(BiTNode));  t2.data = 2;BiTNode t3;    memset(&t3,0,sizeof(BiTNode));  t3.data = 3;BiTNode t4;    memset(&t4,0,sizeof(BiTNode));  t4.data = 4;BiTNode t5;    memset(&t5,0,sizeof(BiTNode));  t5.data = 5;//建立关系t1.lchild = &t2;t1.rchild = &t3;t2.lchild = &t4;t3.lchild = &t5;int num = 0;count_leaf(&t1,&num);   //解决多线程,资源竞争问题printf("叶子节点的个数 %d\n",num);return 0;
}
chunli@http://990487026.blog.51cto.com~/binary_tree$ gcc main.c  -Wall && ./a.out
叶子节点的个数 2
chunli@http://990487026.blog.51cto.com~/binary_tree$

求二叉树的高度:

chunli@http://990487026.blog.51cto.com~/binary_tree$ cat main.c
//树的遍历
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct BiTNode
{int data;struct BiTNode *lchild;struct BiTNode *rchild;
}BiTNode,*BiTree;int tree_dept(BiTNode * root)
{int depth_left = 0;int depth_right = 0;if(!root){return 0;}depth_left = tree_dept(root->lchild);depth_right = tree_dept(root->rchild);return  1+(depth_left>depth_right ? depth_left:depth_right);
}
int main()
{//创建节点BiTNode t1;  memset(&t1,0,sizeof(BiTNode));  t1.data = 1;BiTNode t2;    memset(&t2,0,sizeof(BiTNode));  t2.data = 2;BiTNode t3;    memset(&t3,0,sizeof(BiTNode));  t3.data = 3;BiTNode t4;    memset(&t4,0,sizeof(BiTNode));  t4.data = 4;BiTNode t5;    memset(&t5,0,sizeof(BiTNode));  t5.data = 5;BiTNode t6;    memset(&t6,0,sizeof(BiTNode));  t6.data = 6;//建立关系t1.lchild = &t2;t1.rchild = &t3;t2.lchild = &t4;t3.lchild = &t5;t2.rchild = &t6;int depth = 0;depth = tree_dept(&t1); //解决多线程,资源竞争问题printf("树的高度 %d\n",depth);return 0;
}
chunli@http://990487026.blog.51cto.com~/binary_tree$ gcc main.c  -Wall &&  ./a.out
树的高度 3
chunli@http://990487026.blog.51cto.com~/binary_tree$


二叉树的拷贝:

chunli@http://990487026.blog.51cto.com~/binary_tree$ cat main.c
//树的遍历
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct BiTNode
{int data;struct BiTNode *lchild;struct BiTNode *rchild;
}BiTNode,*BiTree;int tree_dept(BiTNode * root)
{int depth_left = 0;int depth_right = 0;if(!root){return 0;}depth_left = tree_dept(root->lchild);depth_right = tree_dept(root->rchild);return  1+(depth_left>depth_right ? depth_left:depth_right);
}BiTNode* CopyTree(BiTNode *T)
{BiTNode *newNode = NULL;BiTNode *newLp = NULL;BiTNode *newRp = NULL;if(!T){return NULL;}if(T->lchild)    //拷贝左子树{newLp = CopyTree(T->lchild);}else   //如果左子树为NULL{newLp = NULL;}if(T->rchild)//拷贝右子树{newRp = CopyTree(T->rchild);}else{newRp = NULL;}//拷贝根节点newNode = (BiTNode *)malloc(sizeof(BiTNode));memset(newNode,0,sizeof(BiTNode));if(!newNode){return NULL;}newNode->lchild = newLp;newNode->rchild = newRp;newNode->data = T->data;   return newNode;
}void in_Order(BiTNode * root)  //中序遍历
{if(root == NULL){return ;}in_Order(root->lchild);//遍历左子树printf("%d ",root->data);in_Order(root->rchild);//遍历右子树
}int main()
{//创建节点BiTNode t1;  memset(&t1,0,sizeof(BiTNode));  t1.data = 1;BiTNode t2;    memset(&t2,0,sizeof(BiTNode));  t2.data = 2;BiTNode t3;    memset(&t3,0,sizeof(BiTNode));  t3.data = 3;BiTNode t4;    memset(&t4,0,sizeof(BiTNode));  t4.data = 4;BiTNode t5;    memset(&t5,0,sizeof(BiTNode));  t5.data = 5;BiTNode t6;    memset(&t6,0,sizeof(BiTNode));  t6.data = 6;//建立关系t1.lchild = &t2;t1.rchild = &t3;t2.lchild = &t4;t3.lchild = &t5;t2.rchild = &t6;int depth = 0;depth = tree_dept(&t1); //解决多线程,资源竞争问题printf("树的高度 %d\n",depth);printf("中序遍历t1\n");in_Order(&t1);printf("\n");printf("中序遍历拷贝树\n");BiTNode *root = CopyTree(&t1);in_Order(root);printf("\n");return 0;
}
chunli@http://990487026.blog.51cto.com~/binary_tree$ gcc main.c  -Wall  && ./a.out
树的高度 3
中序遍历t1
4 2 6 1 5 3
中序遍历拷贝树
4 2 6 1 5 3
chunli@http://990487026.blog.51cto.com~/binary_tree$



二叉树的遍历-中序遍历非递归算法`栈的非常经典案例

中序 遍历的几种情况

分析1:什么时候访问根、什么时候访问左子树、什么访问右子树

       当左子树为空或者左子树已经访问完毕以后,再访问根

       访问完毕根以后,再访问右子树。

分析2:为什么是栈,而不是其他队列。

        先走到的后访问、后走到的先访问,显然是栈结构

分析3:结点所有路径情况

步骤1:

如果结点有左子树,该结点入栈;

如果结点没有左子树,访问该结点;

步骤2:

如果结点有右子树,重复步骤1;

如果结点没有右子树(结点访问完毕),回退,让栈顶元素出栈,访问栈顶元素,并访问右子树,重复步骤1

如果栈为空,表示遍历结束。

注意:入栈的结点表示,本身没有被访问过,同时右子树也没有被访问过。

分析4:有一个一直往左走入栈的操作


二叉树的遍历-中序遍历非递归算法,STL代码实现

chunli@http://990487026.blog.51cto.com~/binary_tree$ cat main.cpp
//树的非递归遍历(中序遍历)
//  g++ main.cpp  -Wall  && ./a.out
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
using namespace std;typedef struct BiTNode
{int data;struct BiTNode *lchild;struct BiTNode *rchild;
}BiTNode,*BiTree;void in_Order(BiTNode * root)  //中序遍历
{if(root == NULL){return ;}in_Order(root->lchild);//遍历左子树printf("%d ",root->data);in_Order(root->rchild);//遍历右子树
}BiTNode* go_left(BiTNode *T,stack<BiTNode *> *s)//一直往左走,直到找到中序遍历的起点,注意C++的引用*s->&s
{if(!T){return NULL;}while(T->lchild)//如果T有左孩子,就入栈{//s.push(T);  如果上面参数带有引用(*s).push(T);T = T->lchild;}return T;//如果T没有左孩子,就返回
}void in_Order2(BiTNode * T)
{stack<BiTNode *> s;//使用C++ STL库,当然也可以使用自己的栈API//BiTNode* t = go_left(T,s);//如果go_left函数参数是引用可以直接这么写BiTNode* t = go_left(T,&s);while(t)//回到了起点{printf("%d ",t->data);//打印 if(t->rchild)//如果有右子树{//t = go_left(t->rchild,s);//回到右子树中序遍历的起点,如果go_left函数参数是引用可以直接这么写 t = go_left(t->rchild,&s);//回到右子树中序遍历的起点    }else if (!s.empty())//如果t没有右子树,根据栈指示,回退{t = s.top();s.pop();}else//如果t没有右子树,且栈为空{t = NULL;}}
}int main()
{//创建节点BiTNode t1;  memset(&t1,0,sizeof(BiTNode));  t1.data = 1;BiTNode t2;    memset(&t2,0,sizeof(BiTNode));  t2.data = 2;BiTNode t3;    memset(&t3,0,sizeof(BiTNode));  t3.data = 3;BiTNode t4;    memset(&t4,0,sizeof(BiTNode));  t4.data = 4;BiTNode t5;    memset(&t5,0,sizeof(BiTNode));  t5.data = 5;BiTNode t6;    memset(&t6,0,sizeof(BiTNode));  t6.data = 6;//建立关系t1.lchild = &t2;t1.rchild = &t3;t2.lchild = &t4;t3.lchild = &t5;t2.rchild = &t6;printf("递归中序遍历t1\n");in_Order(&t1);printf("\n");printf("非递归中序遍历t1\n");in_Order2(&t1);printf("\n");return 0;
}
chunli@http://990487026.blog.51cto.com~/binary_tree$ g++ main.cpp  -Wall  && ./a.out
递归中序遍历t1
4 2 6 1 5 3
非递归中序遍历t1
4 2 6 1 5 3
chunli@http://990487026.blog.51cto.com~/binary_tree$

利用C++ STL实现 顺序存储  泛型 API


项目文件

chunli@http://990487026.blog.51cto.com~/binary_tree$ tree
.
├── main.cpp
├── SeqList.cpp
└── SeqList.h0 directories, 3 files

main.c

chunli@http://990487026.blog.51cto.com~/binary_tree$ cat main.cpp
//g++ main.cpp  -Wall  && ./a.out
//利用C++ STL实现 顺序存储  泛型 API#include <iostream>
#include <stdio.h>
#include <string.h>
#include "SeqList.cpp"
using namespace std;struct Teacher
{char name[64];int age;
};void fun()
{int i = 0;struct Teacher  tmp;struct Teacher  t1; t1.age = 31;struct Teacher  t2;    t2.age = 32;struct Teacher  t3;    t3.age = 33;SeqList<Teacher> list(10);//创建顺序表list.insert(t1,0);//头插法list.insert(t2,0);//头插法list.insert(t3,0);//头插法//遍历链表for(i=0;i<list.getLen();i++){list.get(i,tmp);cout <<tmp.age <<"  get\n";}//循环删除while(list.getLen() > 0){list.del(0,tmp);头删除cout <<tmp.age <<" del\n";}
}int main()
{fun();return 0;
}
chunli@http://990487026.blog.51cto.com~/binary_tree$


SeqList.cpp 

chunli@http://990487026.blog.51cto.com~/binary_tree$ cat SeqList.cpp
#include <stdio.h>
#include "SeqList.h"
template <typename T>
SeqList<T>::SeqList(int Capacity)
{this->pArray = new T[Capacity];this->capacity = Capacity;this->len = 0;
}template <typename T>
SeqList<T>::~SeqList(void)
{delete [] this->pArray;this->pArray = NULL;this->capacity = 0;this->len = 0;}template <typename T>
int SeqList<T>::getLen()
{return this->len;
}template <typename T>
int SeqList<T>::getCapacity()
{return this->capacity;
}template <typename T>
int SeqList<T>::insert(T &t,int pos)
{int i = 0;if(pos <0){return -1;}for(i=this->len;i>pos;i--){pArray[i] = pArray[i-1];}pArray[i] = t;//STL元素保存时,通过复制机制实现的,你的类要可以复制才行this->len++;return 0;
}template <typename T>
int SeqList<T>::get(int pos,T &t)
{if(pos <0){return -1;}t = pArray[pos];return 0;
}template <typename T>
int SeqList<T>::del(int pos,T &t)
{int i = 0;t = pArray[pos];for(i=pos+1;i<this->len;i++){pArray[i-1] = pArray[i];}this->len--;return 0;
}chunli@http://990487026.blog.51cto.com~/binary_tree$



SeqList.h

chunli@http://990487026.blog.51cto.com~/binary_tree$ cat SeqList.h
#pragma once
template <typename T>
class SeqList
{
public:SeqList(int Capacity);~SeqList(void);int getLen();int getCapacity();int insert(T &t,int pos);int get(int pos,T &t);int del(int pos,T &t);
private:int len;int capacity;T *pArray; };
chunli@http://990487026.blog.51cto.com~/binary_tree$


编译运行

chunli@http://990487026.blog.51cto.com~/binary_tree$ g++ main.cpp SeqList.cpp -Wall  && ./a.out
33  get
32  get
31  get
33 del
32 del
31 del
chunli@http://990487026.blog.51cto.com~/binary_tree$




泛型编程的威力,指针搞起来

主程序稍作修改,其他都不变:

chunli@http://990487026.blog.51cto.com~/binary_tree$ cat main.cpp
//g++ main.cpp  -Wall  && ./a.out
//利用C++ STL实现 顺序存储  泛型 API#include <iostream>
#include <stdio.h>
#include <string.h>
#include "SeqList.cpp"
using namespace std;struct Teacher
{char name[64];int age;
};void fun()
{int i = 0;struct Teacher  *tmp;struct Teacher  t1;    t1.age = 31;struct Teacher  t2;    t2.age = 32;struct Teacher  t3;    t3.age = 33;struct Teacher  *p1 = &t1;    struct Teacher  *p2 = &t2; struct Teacher  *p3 = &t3; SeqList<Teacher *> list(10);//创建顺序表list.insert(p1,0);//头插法list.insert(p2,0);//头插法list.insert(p3,0);//头插法//遍历链表for(i=0;i<list.getLen();i++){list.get(i,tmp);cout <<tmp->age <<"  get\n";}//循环删除while(list.getLen() > 0){list.del(0,tmp);头删除cout <<tmp->age <<" del\n";}
}int main()
{fun();return 0;
}编译运行:
chunli@http://990487026.blog.51cto.com~/binary_tree$ g++ main.cpp SeqList.cpp -Wall  && ./a.out
33  get
32  get
31  get
33 del
32 del
31 del
chunli@http://990487026.blog.51cto.com~/binary_tree$

二叉树的创建 #号方法

chunli@http://990487026.blog.51cto.com~/tree_up$ cat main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef struct BiTNode
{int data;struct BiTNode *lchild;struct BiTNode *rchild;
}BiTNode,*BiTree;void in_Order(BiTNode * root)  //先序遍历
{if(root == NULL){return ;}printf("%c",root->data);in_Order(root->lchild);//遍历左子树in_Order(root->rchild);//遍历右子树
}BiTNode* create_tree()//先序创建
{BiTNode *node = NULL;BiTNode *pleft  = NULL;BiTNode *pright = NULL;char c = getchar(); if(c == '#'){return NULL;}else{node = (BiTNode*)malloc(sizeof(BiTNode));memset(node,0,sizeof(BiTNode));node->data = c;pleft = create_tree();if(pleft != NULL){node->lchild = pleft;}else{node->lchild = NULL;}pright = create_tree();if(pleft != NULL){node->rchild = pright;}else{node->rchild = NULL;}}return node;
}void free_tree(BiTNode* T)
{if(!T){return ;}if(T->lchild){free_tree(T->lchild);T->lchild = NULL;}if(T->rchild){free_tree(T->rchild);T->rchild = NULL;}if(T){free(T);T = NULL;}
}int  main()
{BiTNode *p = create_tree();   in_Order(p);            printf("\n");free_tree(p);return 0;
}
chunli@http://990487026.blog.51cto.com~/tree_up$
chunli@http://990487026.blog.51cto.com~/tree_up$ gcc main.c  -Wall  -g && ./a.out
1234##45678########
123445678
chunli@http://990487026.blog.51cto.com~/tree_up$


面试题-画二叉树

面试题-画二叉树2

数据结构演示工具

二叉树的非递归遍历,C语言基于栈API实现


项目文件:

chunli@http://990487026.blog.51cto.com~/tree_2$ tree
.
├── linklist.c
├── linklist.h
├── linkstack.c
├── linkstack.h
└── main.c
0 directories, 5 files

源代码:

linklist.c 

chunli@http://990487026.blog.51cto.com~/tree_2$ cat linklist.c #include <stdio.h>
#include <stdlib.h>
#include <string.h>#include "linklist.h"typedef struct _tag_LinkList
{//这个句柄里面,需要保存所有节点信息。需要有一个起始点//就是带头节点的链表。。。LinkListNode header;int length;
}TLinkList;LinkList* LinkList_Create()
{TLinkList *ret = (TLinkList *)malloc(sizeof(TLinkList));if (ret == NULL){return NULL;}//memset(ret, 0, sizeof(TLinkList));ret->header.next = NULL;ret->length = 0;return ret;
}void LinkList_Destroy(LinkList* list)
{if (list == NULL){return ;}free(list);return ;
}void LinkList_Clear(LinkList* list)
{TLinkList *tList =NULL;if (list == NULL){return ;}tList = (TLinkList *)list;tList->length = 0;tList->header.next = NULL;return ;
}int LinkList_Length(LinkList* list)
{TLinkList *tList = (TLinkList *)list;if (tList == NULL){return -1;}return tList->length;
}int LinkList_Insert(LinkList* list, LinkListNode* node, int pos)
{int i = 0;TLinkList *tList  = NULL;LinkListNode *current = NULL;tList = (TLinkList *)list;if (list==NULL || node==NULL) //modify by bombing 2014.06.26{return -1;}//准备环境让辅助指针变量 指向链表头节点current = &tList->header;for (i=0; i<pos &&(current->next!=NULL); i++){current = current->next;}//让node节点链接后续链表node->next = current->next ;//让前边的链表。链接nodecurrent->next = node;tList->length ++;  return 0;
}LinkListNode* LinkList_Get(LinkList* list, int pos)
{int i = 0;TLinkList *tList  = NULL;LinkListNode *current = NULL;LinkListNode *ret = NULL;tList = (TLinkList *)list;if (list == NULL || pos <0 ||pos>=tList->length){return NULL;}//准备环境让辅助指针变量 指向链表头节点current = &tList->header;for (i=0; i<pos &&(current->next!=NULL); i++){current = current->next;}ret = current->next;return ret;
}LinkListNode* LinkList_Delete(LinkList* list, int pos)
{int i = 0;TLinkList *tList  = NULL;LinkListNode *current = NULL;LinkListNode *ret = NULL;tList = (TLinkList *)list;if (list == NULL || pos <0 ||pos>=tList->length){return NULL;}//准备环境让辅助指针变量 指向链表头节点current = &tList->header;for (i=0; i<pos &&(current->next!=NULL); i++){current = current->next;}ret = current->next;//删除算法current->next =ret->next;tList->length--;return ret;
}
chunli@http://990487026.blog.51cto.com~/tree_2$

linklist.h

chunli@http://990487026.blog.51cto.com~/tree_2$ cat linklist.h
#ifndef _MYLINKLIST_H_
#define _MYLINKLIST_H_typedef void LinkList;
/*
typedef struct _tag_LinkListNode LinkListNode;
struct _tag_LinkListNode
{LinkListNode* next;
};
*/
typedef struct _tag_LinkListNode
{struct _tag_LinkListNode* next;
}LinkListNode;LinkList* LinkList_Create();void LinkList_Destroy(LinkList* list);void LinkList_Clear(LinkList* list);int LinkList_Length(LinkList* list);int LinkList_Insert(LinkList* list, LinkListNode* node, int pos);LinkListNode* LinkList_Get(LinkList* list, int pos);LinkListNode* LinkList_Delete(LinkList* list, int pos);#endifchunli@http://990487026.blog.51cto.com~/tree_2$


linkstack.c

chunli@http://990487026.blog.51cto.com~/tree_2$ cat linkstack.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "linkstack.h"
#include "linklist.h"
typedef struct linkstack_node
{LinkListNode node;//让万象包含链表void *item; //栈的业务节点
}linkstack_node;LinkStack* LinkStack_Create()//创建一个栈,相当于创建一个线性表
{return LinkList_Create();
}void LinkStack_Destroy(LinkStack* stack)//销毁一个栈,相当于销毁一个线性表
{LinkStack_Clear(stack);LinkList_Destroy(stack);return ;
}void LinkStack_Clear(LinkStack* stack)//清空一个栈,相当于清空一个线性表
{//清空栈的时候,涉及到元素生命周期管理if(stack == NULL){return;}while(LinkStack_Size(stack) > 0){LinkStack_Pop(stack);//释放链表节点}return ;
}int LinkStack_Push(LinkStack* stack, void* item)//向线性表的头部插入元素
{linkstack_node *tmp = (linkstack_node*)malloc(sizeof(linkstack_node));if(tmp == NULL){return -1;}memset(tmp,0,sizeof(linkstack_node));tmp->item = item;int ret = LinkList_Insert(stack,(LinkListNode*)tmp,0);//把数据转换成链表的业务节点if(ret != 0){printf("数据插入失败!\n");if(tmp != NULL)//业务失败时,及时释放内存{free(tmp);}return -2;}return 0;
}void* LinkStack_Pop(LinkStack* stack)//相当于从线性表的头部弹出元素
{linkstack_node *tmp = NULL;//返回一个linkstack_nodetmp = (linkstack_node *)LinkList_Delete(stack,0);//把链表节点转成业务节点if(tmp == NULL){return NULL;}void *item = tmp->item;//还原业务节点free(tmp);        //干掉链表节点return item;
}void* LinkStack_Top(LinkStack* stack)//获取栈顶元素
{linkstack_node *tmp = (linkstack_node *)LinkList_Get(stack,0);if(tmp == NULL){return NULL;}return tmp->item;
}int LinkStack_Size(LinkStack* stack)//求栈的大小,相当于求线性表的额length
{return LinkList_Length(stack);
}chunli@http://990487026.blog.51cto.com~/tree_2$


linkstack.h

chunli@http://990487026.blog.51cto.com~/tree_2$ cat linkstack.h
#ifndef _MY_LINKSTACK_H_
#define _MY_LINKSTACK_H_typedef void LinkStack;LinkStack* LinkStack_Create();void LinkStack_Destroy(LinkStack* stack);void LinkStack_Clear(LinkStack* stack);int LinkStack_Push(LinkStack* stack, void* item);void* LinkStack_Pop(LinkStack* stack);void* LinkStack_Top(LinkStack* stack);int LinkStack_Size(LinkStack* stack);#endif //_MY_LINKSTACK_H_chunli@http://990487026.blog.51cto.com~/tree_2$ chunli@http://990487026.blog.51cto.com~/tree_2$ cat main.c
//非递归遍历二叉树,栈模式API实现#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "linklist.h"
#include "linklist.h"
#include "linkstack.h"typedef struct BiTNode
{int data;struct BiTNode *lchild;struct BiTNode *rchild;
}BiTNode,*BiTree;BiTNode * goleft(BiTNode *T,LinkStack *s)
{int ret = 0;if(T == NULL){return NULL;}while(T->lchild != NULL){ret = LinkStack_Push(s,(void*)T);//压栈if(ret != 0){printf("error in LinkStack_Push \n");}T = T->lchild;}return T;
}void tree_print(BiTNode *root)
{if(!root){return ;}LinkStack *stack = LinkStack_Create();//创建栈if(stack == NULL){printf("error in LinkStack_Create\n");}BiTNode *tmp_node = goleft(root,stack);while(tmp_node){printf("%d ",tmp_node->data);if(tmp_node->rchild != NULL){tmp_node = goleft(tmp_node->rchild,stack);}else if(LinkStack_Size(stack)>0){tmp_node = (BiTNode *)LinkStack_Top(stack);LinkStack_Pop(stack);}else{tmp_node = NULL;}}printf("\n");
}void in_Order(BiTNode * root)  //中序遍历
{if(root == NULL){return ;}in_Order(root->lchild);//遍历左子树printf("%d ",root->data);in_Order(root->rchild);//遍历右子树
}int main()
{//创建节点BiTNode t1;  memset(&t1,0,sizeof(BiTNode));  t1.data = 1;BiTNode t2;    memset(&t2,0,sizeof(BiTNode));  t2.data = 2;BiTNode t3;    memset(&t3,0,sizeof(BiTNode));  t3.data = 3;BiTNode t4;    memset(&t4,0,sizeof(BiTNode));  t4.data = 4;BiTNode t5;    memset(&t5,0,sizeof(BiTNode));  t5.data = 5;BiTNode t6;    memset(&t6,0,sizeof(BiTNode));  t6.data = 6;//建立关系t1.lchild = &t2;t1.rchild = &t3;t2.lchild = &t4;t3.lchild = &t5;t2.rchild = &t6;printf("  递归遍历"); in_Order(&t1);  printf("\n");printf("非递归遍历");   tree_print(&t1);return 0;
}
chunli@http://990487026.blog.51cto.com~/tree_2$

编译运行:

chunli@http://990487026.blog.51cto.com~/tree_2$ gcc main.c linkstack.c linklist.c  -Wall -g && ./a.out 递归遍历4 2 6 1 5 3
非递归遍历4 2 6 1 5 3
chunli@http://990487026.blog.51cto.com~/tree_2$



线索二叉树[很难]

chunli@http://990487026.blog.51cto.com~/tree_3$ cat main.c
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "math.h"  #define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0#define MAXSIZE 100 /* 存储空间初始分配量 */typedef int Status;   /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef char TElemType;
typedef enum {Link,Thread} PointerTag;  /* Link==0表示指向左右孩子指针, *//* Thread==1表示指向前驱或后继的线索 */
typedef  struct BiThrNode   /* 二叉线索存储结点结构 */
{TElemType data;    /* 结点数据 */struct BiThrNode *lchild, *rchild;    /* 左右孩子指针 */PointerTag LTag;PointerTag RTag;        /* 左右标志 */
} BiThrNode, *BiThrTree;TElemType Nil='#'; /* 字符型以空格符为空 */Status visit(TElemType e)
{printf("%c ",e);return OK;
}/* 按前序输入二叉线索树中结点的值,构造二叉线索树T */
/* 0(整型)/空格(字符型)表示空结点 */
Status CreateBiThrTree(BiThrTree *T)
{ TElemType h;scanf("%c",&h);if(h==Nil)*T=NULL;else{*T=(BiThrTree)malloc(sizeof(BiThrNode));if(!*T)exit(OVERFLOW);(*T)->data=h; /* 生成根结点(前序) */CreateBiThrTree(&(*T)->lchild); /* 递归构造左子树 */if((*T)->lchild) /* 有左孩子 */(*T)->LTag=Link;CreateBiThrTree(&(*T)->rchild); /* 递归构造右子树 */if((*T)->rchild) /* 有右孩子 */(*T)->RTag=Link;}return OK;
}BiThrTree pre; /* 全局变量,始终指向刚刚访问过的结点 */
/* 中序遍历进行中序线索化 */
void InThreading(BiThrTree p)
{ if(p){InThreading(p->lchild); /* 递归左子树线索化 */if(!p->lchild) /* 没有左孩子 */{p->LTag=Thread; /* 前驱线索 */           p->lchild=pre; /* 左孩子指针指向前驱 */}if(!pre->rchild) /* 前驱没有右孩子 */{pre->RTag=Thread; /* 后继线索 */pre->rchild=p; /* 前驱右孩子指针指向后继(当前结点p) */}pre=p; /* 保持pre指向p的前驱 */InThreading(p->rchild); /* 递归右子树线索化 */}
}/* 中序遍历二叉树T,并将其中序线索化,Thrt指向头结点 */
Status InOrderThreading(BiThrTree *Thrt,BiThrTree T)
{ *Thrt=(BiThrTree)malloc(sizeof(BiThrNode));if(!*Thrt)exit(OVERFLOW);(*Thrt)->LTag=Link; /* 建头结点 */(*Thrt)->RTag=Thread;(*Thrt)->rchild=(*Thrt); /* 右指针回指 */if(!T) /* 若二叉树空,则左指针回指 */(*Thrt)->lchild=*Thrt;else{(*Thrt)->lchild=T;pre=(*Thrt);InThreading(T); /* 中序遍历进行中序线索化 */pre->rchild=*Thrt;pre->RTag=Thread; /* 最后一个结点线索化 */(*Thrt)->rchild=pre;}return OK;
}/* 中序遍历二叉线索树T(头结点)的非递归算法 */
Status InOrderTraverse_Thr(BiThrTree T)
{ BiThrTree p;p=T->lchild; /* p指向根结点 */while(p!=T){ /* 空树或遍历结束时,p==T */while(p->LTag==Link)p=p->lchild;if(!visit(p->data)) /* 访问其左子树为空的结点 */return ERROR;while(p->RTag==Thread&&p->rchild!=T){p=p->rchild;visit(p->data); /* 访问后继结点 */}p=p->rchild;}return OK;
}int main()
{BiThrTree H,T;printf("请按前序输入二叉树(如:'ABDH##I##EJ###CF##G##')\n");CreateBiThrTree(&T); /* 按前序产生二叉树 */InOrderThreading(&H,T); /* 中序遍历,并中序线索化二叉树 */printf("中序遍历(输出)二叉线索树:\n");InOrderTraverse_Thr(H); /* 中序遍历(输出)二叉线索树 */printf("\n");return 0;
}chunli@http://990487026.blog.51cto.com~/tree_3$ gcc main.c -Wall && ./a.out
请按前序输入二叉树(如:'ABDH##I##EJ###CF##G##')
ABDH##I##EJ###CF##G##
中序遍历(输出)二叉线索树:
H D I B J E A F C G
chunli@http://990487026.blog.51cto.com~/tree_3$



霍夫曼树(最优二叉树)

本文谢绝转载,原文来自http://990487026.blog.51cto.com

转载于:https://blog.51cto.com/990487026/1852987

数据结构与算法 3:二叉树,遍历,创建,释放,拷贝,求高度,面试,线索树相关推荐

  1. 数据结构与算法之二叉树的序列化和反序列化及判断一棵树是否为平衡二叉树

    数据结构与算法之二叉树的序列化和反序列化及判断一棵树是否为平衡而二叉树 目录 二叉树的序列化和反序列化 判断一棵树是否为平衡而二叉树 1. 二叉树的序列化和反序列化 1. 递归版本序列化和反序列化 代 ...

  2. 数据结构与算法_二叉树遍历

    文章目录 0. 前言 0.1 二叉树的结构体 1.二叉树的遍历 1.1 二叉树前序遍历(根→左→右) 1.2 二叉树的中序遍历(左-根-右) 1.3 后序遍历(左-右-根) 1.4 二叉树层序遍历结果 ...

  3. 【数据结构与算法】二叉树遍历

    两种遍历方式 广度优先遍历和深度优先遍历,都可用递归和非递归实现 定义二叉树 class Node:def __init__(self, root):self.root = rootself.left ...

  4. 数据结构与算法之二叉树的先序遍历,中序遍历,后序遍历

    数据结构与算法之二叉树的先序遍历,中序遍历,后移遍历 目录 实现二叉树的先序,中序,后序遍历,包括递归方式和非递归方式 在二叉树中找到一个节点的后继节点 1. 实现二叉树的先序,中序,后序遍历,包括递 ...

  5. 数据结构与算法练习-二叉树中序遍历

    python数据结构与算法练习-二叉树中序遍历 二叉树中序遍历 思路 python实现 二叉树中序遍历 链接: link. 给定一个二叉树的根节点 root ,返回它的 中序 遍历. 样例 输入:ro ...

  6. 数据结构与算法:二叉树专题

    数据结构与算法:二叉树专题 前言 前提条件 基础知识 二叉树链式存储结构 二叉树中序遍历 二叉树层序遍历 常见编程题 把一个有序整数数组放到二叉树中 逐层打印二叉树结点数据 求一棵二叉树的最大子树和 ...

  7. 常考数据结构与算法:输出二叉树的右视图

    题目描述 请根据二叉树的前序遍历,中序遍历恢复二叉树,并打印出二叉树的右视图 上图树的右视图为:{1,4,3,7} 做此题之前可以先做下面3道题: 1. 常考数据结构与算法:求二叉树的层序遍历 2.常 ...

  8. 数据结构与算法之-----二叉树(一)

    [ 写在前面的话:本专栏的主要内容:数据结构与算法. 1.对于初识数据结构的小伙伴们,鉴于后面的数据结构的构建会使用到专栏前面的内容,包括具体数据结构的应用,所使用到的数据结构,也是自己构建的,未使用 ...

  9. 数据结构与算法之二叉树广度遍历、深度遍历总结

    什么是树,它是和链表一样都是一种抽象数据类型(ADT),包括数据结构和对数据的操作. 树是一种二维平面的数据结构结构,它也是由节点组成的,只是它的后继节点不止一个,而链表的后继节点只有一个. 树具有以 ...

最新文章

  1. python 画柱状图-python使用Plotly绘图工具绘制柱状图
  2. MongoDB基本概念学习 - 文档
  3. Git 提交 .gitignore文件
  4. JDK5.0环境下配置PKCS#11
  5. java netty swap高_Netty 超时机制及心跳程序实现
  6. iOS之由身份证号返回性别
  7. 计算机专业的学生该选择日后的人生道路?继续从事IT还是考公务员……
  8. apache php设置404页面,详细介绍通过配置Apache实现404页面替换
  9. sql中用于子查询的几个关键词 any(some是 any的别名),all,in,exists
  10. 如何让遮罩层悬浮在object标签中
  11. c语言 车牌识别 源代码,车牌识别--模板库C语言数组的制做
  12. 设置自定义电脑屏幕分辨率
  13. CSS 网页定位与布局
  14. 沧小海基于xilinx srio核的学习笔记之第三章 xilinx srio核介绍(一)结构介绍
  15. 计算机硬件相关行业,2021年中国电脑硬件行业市场规模及发展前景预测分析(图)...
  16. 区块链安全和隐私问题有点与众不同
  17. Access2003中自定义菜单栏
  18. php 车牌号限号,车辆尾号限行API免费接口,车辆尾号限行API接口付费定制-进制数据...
  19. GooglePlay 应用内评分测试
  20. 对AnyChat录屏解决方案的调研报告

热门文章

  1. 信号与槽QVariant传递结构体指针
  2. 诡异的 BOM 字符 \ufeff
  3. 网站访客 简易日志记录
  4. 更改自身web项目的图标(默认为tomcat的小喵咪)
  5. 使用Jenkins的任务自动跑脚本后发现,服务没有起来
  6. centos7使用记录
  7. 绿色网格称其IT环境评估工具取得成功
  8. R1Soft——先进的数据保护系统
  9. error: undefined reference to `PathTrace::PathTrace(World*)' (Codeblocks, C++)
  10. PTA: 6-4建立学生信息链表(20分)