标签:for creates type pos 读数 二次 sea size id3
注:本文使用的网课资源为中国大学MOOC
https://www.icourse163.org/course/ZJU-93001
查找:根据某个给定的关键字K,从集合R中找出关键字与K相同的记录。
静态查找:集合中的记录是固定的,没有插入删除的操作,只有查找;
动态查找:集合中记录是动态变化的,除查找,还可能发生插入和删除。
方法1:顺序查找
int SequentialSearch( StaticTable *Tbl, ElementType K)
{
//在表Tbl[1]~Tbl[n]中查找关键字为K的数据元素
int i;
Tbl->Element[0] = K; //建立哨兵
for (i=Tbl->Length; Tbl->Element[i]!=K; i--);
return i; //查找成果则返回所在单元下标;不成功则返回0
}
顺序查找的时间复杂度为O(n)。
方法2:二分查找
int BinarySearch( StaticTable *Tbl, ElementType K)
{
int left, right, mid, NotFound = -1;
left = 1; //初始左边界
right = Tbl->Length; //初始右边界
while ( left <= right )
{
mid = (left+right)/2; //计算中间元素坐标
if ( K < Tbl->Element[mid] )
right = mid-1; //调整右边界
else if ( K > Tbl->Element[mid] )
left = mid+1; //调整左边界
else
return mid; //查找成功,返回数据元素的下标
}
return NotFound; //查找不成功,返回-1
}
二分查找算法具有对数时间复杂度O(log(N))。
树(Tree): n(n≥0)个结点构成的有限集合。当n=0时,称为空树,对于任意一棵非空树,它具备以下性质:
二叉树T:一个有穷的结点组合
特殊的二叉树
类型名称:二叉树
数据对象集:一个有穷的结点集合。若不为空,则由根结点和其左、右二叉子树组成。
操作集:\(BT \in BinTree\),\(Item \in ElementType\),重要操作有:
Boolean IsEmpty( BinTree BT); //判别BT是否为空
void Traversal( BinTree BT ); //遍历,按某顺序访问每一个结点
BinTree CreatBinTree();//创建一个二叉树
/* 常见的遍历方法 */
void PreOrderTraversal( BinTree BT ); //先序:根-左-右
void InOrderTraversal( BinTree BT ); //中序:左-根-右
void PostOrderTraversal( BinTree BT ); //后序:左-右-根
void LevelOrderTraversal( BinTree BT ); //层次遍历:从上到下,从左到右
顺序存储结构
完全二叉树:按从上到下、从左到右顺序存储n个结点的完全二叉树的结点父子关系:
链表存储结构
typedef struct TreeNode *Position
typedef Position BinTree
struct TreeNode
{
ElementTyoe Data;
BinTree Left;
BinTree right;
}
(1) 先序遍历
遍历过程:
void PreOrderTraversal( BinTree BT )
{
if ( BT )
{
printf("%d", BT->Data); //根结点
PreOrderTraversal( BT->Left ); //左子树
PreOrderTraversal( BT->Right ); //右子树
}
}
(2) 中序遍历
遍历过程:
void InOrderTraversal( BinTree BT )
{
if ( BT )
{
InOrderTraversal( BT->Left ); //左子树
printf("%d", BT->Data); //根结点
InOrderTraversal( BT->Right ); //右子树
}
}
(3) 后序遍历
遍历过程:
void PostOrderTraversal( BinTree BT )
{
if ( BT )
{
PostOrderTraversal( BT->Left ); //左子树
PostOrderTraversal( BT->Right ); //右子树
printf("%d", BT->Data); //根结点
}
}
先序、中序和后序遍历过程中结果结点的路线是一样的,只是访问各结点的时机不同。
非递归算法实现的基本思路:使用堆栈
(1) 中序遍历
void InOrderTraversal( BinTree BT )
{
BinTree T = BT;
Stack S = CreatStack(MaxSize); //创建并初始化堆栈S
while (T || !IsEmpty(S))
{
while (T) //一直向左并将沿途结点压入堆栈
{
Push(S, T);
T = T->Left;
}
if ( !IsEmpty(S))
{
T = Pop(S); //结点弹出堆栈
printf("%5d", T->Data); //打印结点
T = T->Right; //转向右子树
}
}
}
(2) 先序遍历
void PreOrderTraversal( BinTree BT )
{
BinTree T = BT;
Stack S = CreateStack(); // 创建并初始化堆栈 S
while(T || !IsEmpty(S)) // 当树不为空或堆栈不空
{
while(T)
{
Push(S,T); // 压栈,第一次遇到该结点
printf("%d",T->Data); // 访问结点
T = T->Left; // 遍历左子树
}
if(!IsEmpty(S)) // 当堆栈不空
{
T = Pop(S); // 出栈,第二次遇到该结点
T = T->Right; // 访问右结点
}
}
}
(3) 后序遍历
先序的访问顺序是root, left, right 假设将先序左右对调,则顺序变成root, right, left,暂定称之为“反序”。后序遍历的访问顺序为left, right,root ,刚好是“反序”结果的逆向输出。
void PostOrderTraversal( BinTree BT )
{
BinTree T = BT;
Stack S = CreatStack();
Stack N = CreatStack(); //创建并初始化栈N
wihile ( T || !IsEmpty(S) )
{
while(T) /*一直向右并将沿途结点压入堆栈*/
{
Push(S,T);
Push(N,T); //将遍历到的结点压栈,用于反向
T = T->Right; //这里是Right
}
if ( !IsEmpty(S) )
{
T = Pop(S);
T = T->Left;
}
}
while ( !IsEmpty(N) )
{
T = Pop(N);
printf("%5d", T->Data); //将 N 栈中的数据依次弹出并打印
}
}
队列实现:
void LevelTraversal( BinTree BT )
{
if ( !BT )
return; //如果是空树直接返回
BinTree T;
Queue Q = CreatQueue(MaxSize); //创建并初始化队列Q
AddQ( Q, BT );
while (!IsEmpty(Q))
{
T = DeleteQ( Q );
printf("%d\n", T->Data); // 访问取出队列的结点
if ( T->Left )
AddQ( Q, T->Left );
if ( T->Right )
AddQ( Q, T->Right );
}
}
(1) 求二叉树的高度
int PostOrderGetHeight( BinTree BT )
{
int HL, HR, MaxH;
if ( BT )
{
HL = PostOrderGetHeight( BT->Left );
HR = PostOrderGetHeight( BT->Right );
MaxH = (HL>HR) ? HL :HR; // 取左右子树较大的深度
return ( MaxH+1 );
}
else
return 0; // 空树深度为0
}
(2) 根据先序和中序遍历来确定一棵二叉树
分析:
例如:
前序:ABCDEFG
中序:CBDAFEG
先序遍历为"根左右",则 A 是根,对应可以划分出中序中:(CBD)A(FEG),CBD 为左子树,FEG 为右子树,
再根据前序的 BCD,B 为根,划分出中序中(C(B)D)A(FEG),则 C D 分别是 B 的左右子树…最后可得树为:
A
/ B E
/ \ / C D F G
给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称这两棵树是“同构”的。
输入格式:
输入样例:
int main()
{
Tree R1, R2; // 利用结构数组表示二叉树,静态链表
R1 = BuildTree(T1); // 建立二叉树1
R2 = BuildTree(T2); // 建立二叉树2
if ( Isomorphic(R1, R2) ) // 判别是否同构并输出
printf("Yes\n");
else
printf("No\n");
return 0;
}
#include <stdio.h>
#include <stdlib.h> //调用malloc()和free()
#include <malloc.h> //调用malloc()和free()
#include <windows.h> //windows.h里定义了关于创建窗口,消息循环等函数S
#define MaxTree 10
#define Null -1
struct TreeNode
{
char item;
int Left;
int Right; // 注:这里的left和right分别为输入数据的左右子结点索引
} T1[MaxTree], T2[MaxTree]; // 结构数组表示二叉树
/* 创建树并返回根结点 */
int BuildTree(struct TreeNode T[])
{
int i, N;
int Root = 0;
int check[MaxTree];
char cl, cr;
scanf("%d", &N);
if ( !N )
return Null;
for (i = 0; i < N; i++)
check[i] = 0;
for (i = 0; i < N; i++)
{
printf("%d: ",i);
scanf("%c %c %c", &T[i].item, &cl, &cr); // 注意输入时不要有空格,且字母要小写,eg.a12
fflush(stdin); // 微软系统中清空缓冲区的功能函数
// 注意‘’和“”的区别,双引号括起来的是字符串指针,单引号括起来的才是字符
if (cl != '-')
{
T[i].Left = cl - '0';
check[T[i].Left] = 1;
}
else
T[i].Left = Null;
if (cr != '-')
{
T[i].Right = cr - '0';
check[T[i].Right] = 1;
}
else
T[i].Right = Null;
}
for (i = 0; i < N; i++)
if (!check[i])
break;
Root = i;
return Root;
}
/* 判断二叉树是否重构 */
int Ismorphic(int R1, int R2)
{
if ((R1 == Null) && (R2 == Null)) // 均为空
return 1;
if (((R1 == Null) && (R2 != Null)) || ((R1 != Null) && (R2 == Null))) // 其中一个为空
return 0;
if ((T1[R1].Left == Null) && (T2[R1].Left == Null)) // 根结点均没有左子树
return Ismorphic(T1[R1].Right, T2[R2].Right);
if (((T1[R1].Left != Null) && (T2[R2].Left != Null)) && ((T1[T1[R1].Left].item) == (T2[T2[R2].Left].item)))
return (Ismorphic(T1[R1].Left, T2[R2].Left) && Ismorphic(T1[R1].Right, T2[R2].Right));
else
return (Ismorphic(T1[R1].Left, T2[R2].Right) && Ismorphic(T1[R1].Right, T2[R2].Left));
}
int main()
{
int R1, R2; // 利用结构数组表示二叉树,静态链表
printf("T1:\n");
R1 = BuildTree(T1); // 建立二叉树1
printf("T2:\n");
R2 = BuildTree(T2); // 建立二叉树2
if (Ismorphic(R1, R2)) // 判别是否同构并输出
printf("Yes\n");
else
printf("No\n");
system("pause"); //程序暂停,显示按下任意键继续
return 0;
}
标签:for creates type pos 读数 二次 sea size id3
原文地址:https://www.cnblogs.com/Superorange/p/12514512.html