编程笔记 数据结构 第六章 树与二叉树
以后有什么知识盲点就记录一下, 经常拿出来复习才能彻底消化吸收,一个劲儿地往前学是不可行的方法。
typedef struct 和struct
1 首先://注意在C和C++里不同
在C中定义一个结构体类型要用typedef:
typedef struct Student
{
int a;
}Stu;
于是在声明变量的时候就可:Stu stu1;(如果没有typedef就必须用struct Student stu1;来声明)
这里的Stu实际上就是struct Student的别名。Stu==struct Student
另外这里也可以不写Student(于是也不能struct Student stu1;了,必须是Stu stu1;)
typedef struct
{
int a;
}Stu;
但在c++里很简单,直接
struct Student
{
int a;
};
于是就定义了结构体类型Student,声明变量时直接Student stu2;
2.其次:
在c++中如果用typedef的话,又会造成区别:
struct Student
{
int a;
}stu1;//stu1是一个变量
typedef struct Student2
{
int a;
}stu2;//stu2是一个结构体类型=struct Student
使用时可以直接访问stu1.a
但是stu2则必须先 stu2 s2;
然后 s2.a=10;
引用和指针
一、引用的定义
引用是给另外一个变量起别名,所以引用不会分配内存空间。
引用的声明方法:类型标识符 &引用名=目标变量名;(如int &ptr = num;)
二、引用与指针的区别
1、指针是一个实体,需要分配内存空间。引用只是变量的别名,不需要分配内存空间。
2、引用在定义的时候必须进行初始化,并且不能够改变。指针在定义的时候不一定要初始化,并且指向的空间可变。(注:不能有引用的值不能为NULL)
3、有多级指针,但是没有多级引用,只能有一级引用。
4、指针和引用的自增运算结果不一样。(指针是指向下一个空间,引用时引用的变量值加1)
5、sizeof 引用得到的是所指向的变量(对象)的大小,而sizeof 指针得到的是指针本身的大小。
6、引用访问一个变量是直接访问,而指针访问一个变量是间接访问。
#include <iostream>
using namespace std;
void swap(int &a, int &b)
{
int tmp;
tmp = a;
a = b;
b = tmp;
}
int main()
{
int a = 3;
int b = 5;
cout << "before swap, a = " << a << " b = " << b << endl;
swap(a, b);
cout << "after swap, a = " << a << " b = " << b << endl;
return 0;
}
#### 3/24 二叉树练习
引用是给变量了另一个名字,调用时为直接调用变量而指针是分配了一个内存空间并存下变量的地址,属于间接引用。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <queue>
using namespace std;
/*
题目:二叉树
1. 二叉树的创建
2. 四种遍历方法
3. 三种非递归遍历方法
*/
typedef char Elemtype;
typedef struct node
{
struct node *lchild;
struct node *rchild;
Elemtype data;
}BiNode, *BiTree;
// 给结构体node起别名:BiNode,以及结构体的指针的别名:BiTree
void create(BiTree &t)
{
Elemtype x;
cin >> x;
if (x == '#')
{
t = NULL;
}
else
{
t = (BiTree)malloc(sizeof(BiTree));
t->data = x;
create(t->lchild);
create(t->rchild);
}
}
void print(BiTree &t)
{
if (t != NULL)
{
cout << t->data ;
print(t->lchild);
print(t->rchild);
}
}
// 1. 表达式求值 输入一个表达式创建二叉树
void createBD(BiTree &t)
{
Elemtype x;
cin >> x;
if (x != '#')
{
t = (BiTree )malloc(sizeof(BiTree));
t->data = x;
createBD(t->lchild);
createBD(t->rchild);
}else
{
t = NULL;
}
}
int cmp(int a,char op,int b)
{
switch (op)
{
case '+':return a+b;
case '-':return a-b;
case '*':return a*b;
case '/':
if (b!=0)
return a/b;
}
return 0;
}
// 后序遍历计算值
int countV(BiTree &t)
{
int a,b;
if (t!=NULL)
{
if (t->lchild == NULL && t->rchild == NULL)
{
return t->data - '0';
}
else
{
a = countV(t->lchild);
b = countV(t->rchild);
int c = cmp(a,t->data,b);
return c;
}
}
else
return 0;
}
int depth(BiTree &t)
{
if (t == NULL)
return 0;
else
{
int l = depth(t->lchild);
int r = depth(t->rchild);
return l>=r?l+1:r+1;
}
}
// 层次遍历
void level(BiTree &t)
{
queue<BiTree> q;
BiTree p;
if (t) // 空树没有必要遍历了
{
q.push(t); // 根节点入队
while (!q.empty())
{
p = q.front(); // 弹栈一个元素
q.pop();
cout << p->data << ' ';
if (p->lchild)
{
q.push(p->lchild);
}
if (p->rchild)
{
q.push(p->rchild);
}
}
}
}
// 计算二叉树的宽度
struct Node{
BiTree t;
int num; // 结点所在的层次号
};
const int maxSize = 100;
int width(BiTree &t)
{
Node q[maxSize];
int front , rear ;
front = rear = 0;
int mm;
BiTree p;
Node n;
if (t) // 空树没有必要遍历了
{
n.t = t;
n.num = 1;
rear = (rear+1)%maxSize;
q[rear] = n;
while (front != rear)
{
front = (front +1)%maxSize;
p = q[front].t;
// cout << p->data << ' ';
int lno = q[front].num;
if (p->lchild)
{
n.num = lno +1;
n.t = p->lchild;
rear = (rear +1)%maxSize;
q[rear] = n;
}
if (p->rchild)
{
n.num = lno + 1;
n.t = p->rchild;
rear = (rear +1)%maxSize;
q[rear] = n;
}
}
mm = 0;
for (int i=1;i<=n.num;i++)
{
int nn = 0 ;
for (int j=1;j<=rear;j++)
if (q[j].num == i)
++nn;
if (nn > mm)
mm = nn;
}
return mm;
}
else return 0;
}
// 非递归遍历算法
// 先序遍历
void preOrderNon(BiTree &t)
{
BiTree s[maxSize];
BiTree p;
int top = -1;
if (t)
{
s[++top] = t;
//cout << t->data << endl;
while (top != -1)
{
p = s[top--];
cout << p->data << ' ';
if (p->lchild)
{
s[++top] = p->lchild;
}
if (p->rchild)
{
s[++top] = p->rchild;
}
}
}
}
// 中序遍历
void inOrderNon(BiTree &t)
{
BiTree s[maxSize];
int top = -1;
BiTree p;
p = t;
if (t){
while (p!=NULL || top != -1)
{
while (p)
{
s[++top] = p;
p = p->lchild;
}
if (top!=-1)
{
p = s[top--];
cout << p->data << ' ';
p = p->rchild;
}
}
}
}
// 后序遍历
int main()
{
BiTree t;
//create(t);
createBD(t);
// width(t);
//int c = countV(t);
//cout << c << endl;
// print(t);
// cout << width(t)<<endl;
inOrderNon(t);
return 0;
}
二叉树练习 2018/3/26
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
/*
题目:二叉树
1. 创建二叉树 √
2. 三种递归遍历方法+层次遍历法 √
3. 三种非递归遍历方法
4. 求二叉树的深度
6. 求叶子结点的个数
8. 求先序遍历中第K个结点的值
9. 左右子树互换
10.复制二叉树
7. 表达式求值
5. 求二叉树的宽度
*/
typedef char Elemtype;
typedef struct BiNode
{
Elemtype data;
struct BiNode *lchild,*rchild;
}BiNode,*BiTree;
// 1. 先序创建二叉树
void createBiTree(BiTree &t)
{
// 输入一个字符串序列,为NULL的指针表示为#
Elemtype x;
cin >> x;
if ( x == '#')
{
t = NULL;
}
else
{
t = (BiTree )malloc(sizeof(BiTree));
t->data = x;
createBiTree(t->lchild);
createBiTree(t->rchild);
}
}
// 2. 先序递归遍历
// 访问函数
void visited(BiTree p)
{
cout <<p ->data <<' ';
}
void preOrderTraverse(BiTree &t)
{
if (t)
{
visited(t);
preOrderTraverse(t->lchild);
preOrderTraverse(t->rchild);
}
}
// 2. 层次遍历需要队列的辅助,没有递归遍历方法
/*
1. 初始化队列
2. 压入根之前判断根是否为空
3. 取队头 -> 访问结点 -> 压入非空的左孩子和右孩子
4. 队列为空时循环结束
*/
void levelOrder(BiTree &t)
{
queue<BiTree> que ;
BiTree p = t; // p : 遍历指针
if (t) // 根节点不能为空
{
que.push(t);
while (!que.empty())
{
p = que.front();
que.pop();
visited(p);
if (p->lchild)
{
que.push(p->lchild);
}
if (p->rchild)
{
que.push(p->rchild);
}
}
}
}
// 3. 非递归三种遍历方法
// 先序非递归
/*
1. 遇到一个结点首先访问该结点,如果有左子树则继续往左走
2. 到了最左边时弹栈,访问右子树
3. 如果右子树为空则继续弹栈,否则向右子树的左边继续前进
*/
void preOrderUn(BiTree &t)
{
stack<BiTree> st;
BiTree p = t;
while (p!= NULL || !st.empty()) // 当且仅当栈和指针都为空时循环结束
{
while (p)
{
visited(p);
st.push(p);
p = p->lchild;
}
if (!st.empty())
{
p = st.top();
st.pop();
p = p->rchild;
}
}
}
// 中序非递归
void midOrderUn(BiTree t)
{
stack<BiTree> st;
BiTree p = t;
while (p != NULL || !st.empty())
{
while(p)
{
st.push(p);
p = p->lchild;
}
if (!st.empty())
{
p = st.top();
st.pop();
visited(p);
p = p->rchild;
}
}
}
// 后序非递归遍历
/*
1. 第一次访问结点:入栈,isFirst = 1
2. 弹栈如果isFirst == 1,修改isFirst,压栈,往右走
3. 第三次访问如果isFirst = 0,访问结点数据
*/
typedef struct lBiTree
{
BiTree t;
int isFirst;
}lBiTree;
void lastOrderUn(BiTree t)
{
stack<lBiTree> st;
BiTree p = t;
lBiTree l;
while ( p!=NULL || !st.empty())
{
while (p)
{
l.isFirst = 1;
l.t = p;
st.push(l);
p = p->lchild;
}
if (!st.empty())
{
l = st.top();
st.pop();
if (l.isFirst == 1)
{
l.isFirst = 0;
p = l.t->rchild;
st.push(l);
}
else
{
visited(l.t);
p = NULL;
}
}
}
}
// 4. 深度
int depth(BiTree t)
{
if (t == NULL)
return 0;
else
{
int l = depth(t->lchild);
int r = depth(t->rchild);
return l >= r?l+1:r+1;
}
}
// 求叶子结点个数
int leaf(BiTree t)
{
if (t)
{
if (t->lchild == NULL && t->rchild == NULL)
{
return 1;
}
else
{
return leaf(t->lchild)+leaf(t->rchild);
}
}
else
return 0;
}
// 求树的结点个数
int number(BiTree t)
{
if (t)
return 0; //空树没有结点
else{
return 1+number(t->lchild)+number(t->rchild);
}
}
// 左右子树互换
void exchange(BiTree &t)
{
BiTree s;
if (t)
{
s = t->lchild;
t->lchild = t->rchild;
t->rchild = s;
exchange(t->lchild);
exchange(t->rchild);
}
}
// 复制二叉树
BiTree copyBiTree(BiTree &t)
{
BiTree p;
if (t)
{
p = (BiTree)malloc(sizeof(BiTree));
p->data = t->data;
p->lchild = copyBiTree(t->lchild);
p->rchild = copyBiTree(t->rchild);
return p;
}
}
// 表达式求值
int countValue(BiTree t)
{
if (t)
{
if (t->lchild == NULL &&t->rchild == NULL)
{
return t->data-'0';
}
else{
int a = countValue(t->lchild);
int b = countValue(t->rchild);
int c = cmp(a,t->data,b);
return c;
}
}
}
int main()
{
BiTree t;
createBiTree(t);
// preOrderTraverse(t);
// levelOrder(t);
// preOrderUn(t);
//midOrderUn(t);
// lastOrderUn(t);
//cout << depth(t)<<endl;
cout << leaf(t)<<endl;
return 0;
}
3/29 日练习
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
/*
时间:2018/3/26
题目:二叉树
1. 创建二叉树 √
2. 三种递归遍历方法+层次遍历法 √
3. 三种非递归遍历方法 √
4. 求二叉树的深度 √
5. 求叶子结点的个数 √
6. 求先序遍历中第K个结点的值 √
7. 左右子树互换 √
8.复制二叉树 √
9. 表达式求值 √
10. 求二叉树的宽度 √
11.线索二叉树的中序线索化
12.线索二叉树的中序遍历
13.线索二叉树的先序、后序线索化以及遍历方法
*/
typedef char Elemtype;
typedef struct BiNode
{
Elemtype data;
struct BiNode *lchild,*rchild;
}BiNode,*BiTree;
void createBiTree(BiTree &t)
{
Elemtype x;
cin >> x;
if (x!='#')
{
t = (BiTree )malloc(sizeof(BiTree));
t->data = x;
createBiTree(t->lchild);
createBiTree(t->rchild);
}
else
{
t = NULL;
}
}
void visit(BiTree p)
{
cout << p->data <<' ';
}
void preOrder(BiTree &t)
{
if (t)
{
visit(t);
preOrder(t->lchild);
preOrder(t->rchild);
}
}
void levelOrder(BiTree &t)
{
queue<BiTree> que;
BiTree p = t;
if (t)
{
que.push(p);
while (!que.empty()) // 注意这里队空时结束,而不是队和P指针都为空,到最后的时候P不为空
{
p = que.front();
que.pop();
visit(p);
if (p->lchild!=NULL)
que.push(p->lchild);
if (p->rchild!=NULL)
que.push(p->rchild);
}
}
}
void preOrderUn(BiTree &t)
{
stack<BiTree> st;
BiTree p = t;
if (t)
{
while (p || !st.empty())
{
while (p)
{
visit(p);
st.push(p);
p = p->lchild;
}
if (!st.empty())
{
p = st.top();
st.pop();
p = p->rchild;
}
}
}
}
typedef struct
{
BiTree k;
int isFirst;
}PBiTree;
void postOrderUn(BiTree &t)
{
stack<PBiTree> st;
BiTree p = t;
PBiTree tmp;
if (t)
{
while (p || !st.empty())
{
while (p)
{
tmp.isFirst = 1;
tmp.k = p;
st.push(tmp);
p = p->lchild;
}
if (!st.empty())
{
tmp = st.top();
st.pop();
if (tmp.isFirst == 1)
{
tmp.isFirst = 0;
st.push(tmp);
p = tmp.k->rchild;
}else
{
visit(tmp.k);
p = NULL;
}
}
}
}
}
int depth(BiTree &t)
{
if (t->lchild == NULL && t->rchild == NULL)
{
return 1;
}
if (t)
{
int l = depth(t->lchild);
int r = depth(t->rchild);
return l>r?l+1:r+1;
}
}
int leaf(BiTree &t)
{
if (t->lchild == NULL && t->rchild == NULL)
return 1;
if (t)
{
return leaf(t->lchild)+leaf(t->rchild);
}
}
void exchange(BiTree &t)
{
BiTree p;
if (t)
{
p = t->lchild;
t->lchild = t->rchild;
t->rchild = p;
exchange(t->lchild);
exchange(t->rchild);
}
}
int count(int a,char c,int b)
{
return 1;
}
int value(BiTree &t)
{
if (t->lchild == NULL && t->rchild == NULL)
{
return t->data -'0';
}
if (t)
{
int a = value(t->lchild);
int b = value(t->rchild);
int c = count(a,t->data,b);
return c;
}
}
typedef struct
{
BiTree k;
int level;
}WBiTree;
const int MAXSIZE = 20;
int width(BiTree &t)
{
WBiTree que[MAXSIZE];
BiTree p = t;
WBiTree tmp,tmp2;
int front=0,rear = 0;
int level = 1;
if (t)
{
rear = (rear+1)%MAXSIZE;
tmp.k = p;
tmp.level = level;
que[rear] = tmp;
while (front != rear)
{
front = (front+1)%MAXSIZE;
tmp = que[front];
if (tmp.k->lchild)
{
rear = (rear+1)%MAXSIZE;
tmp2.k = tmp.k->lchild;
tmp2.level = tmp.level+1;
que[rear] = tmp2; // 等于根节点+1
}
if (tmp.k->rchild)
{
rear = (rear+1)%MAXSIZE;
tmp2.k = tmp.k->rchild;
tmp2.level = tmp.level+1;
que[rear] = tmp2; // 等于根节点+1
}
}
// 遍历一下que数组,从0-rear,统计每层的结点个数,求最大值
int maxNum = 0;
int num = 1;
int j = 1;
for (int i = 1;i<=rear;i++)
{
if (que[i+1].level == que[i].level)
{
num++;
}
else
{
num = 1;
}
if (num > maxNum)
{
maxNum = num;
}
}
return maxNum;
}
return 0;
}
int main()
{
BiTree t;
createBiTree(t);
// preOrder(t);
// levelOrder(t);
// preOrderUn(t);
//postOrderUn(t);
//cout << depth(t) << endl;
//cout << leaf(t) << endl;
cout << width(t) << endl;
return 0;
}