1.静态查找
0位置为哨兵
typedef struct LNode *List;
struct LNode {
ElementType
Element [MAXSIZE] ;
int Length;
};
int SequentialSearch(List Tbl,ElementType K)
{ /*在表Element[1]~Element[n]中查找关键字为K的数据元素*/
int i;
Tbl -> Element[0] = K;
for(i = Tbl->Length; Tbl->Element[i] != K; i--)
return i; /*查找成功返回所在单元下标;不成功返回0*/
}
2.二分查找
int BinarySearch(List Tbl, ElementType K)
{
*在表Tbl中查找大健了为K的数据元素*1
int left, right, mid, NoFound=-1;
left= 1;
right = Tbl->Length;
while (left <= right )
{
mid = (left+right) / 2;计算中间元素坐标*/
if( K < Tbl->Element[mid]) right = mid-1; 1*调 整右边界*/
else if( K > Tbl->Element[mid) left = mid+1;调 整左边界*/
else return mid; "查找成功, 返回数据元素的下标*1
}
return NotFound;
}
ASL,是查找算法的查找成功时的平均查找长度的缩写
树的定义:
子树是不相交的;
除了根结点外,每个结点有且仅有一个父结点;
一棵N个结点的树有N-1条边。
树的一些基本术语
1.结点的度(Degree) :结点的子树个数
2. 树的度:树的所有结点中最大的度数
3.叶结点(Leaf) :度为0的结点
4.父结点(Parent) :有子树的结点是其子树的根结点的父结点
5. 子结点(Child) :若A结点是B结点的父结点,则称B结点是A结点的子结点:子结点也,称孩子结点。
6. 兄弟结点(Sibling) :具有同一父结点的各结点彼此是兄弟结点。
7.路径和路径长度: 从结点n到n的路径为- -个结点序列n, n2... nk, n是n4+1的父结点。路径所包含边的个数为路径的长度。
9.祖先结点(Ancestor):沿树根到某一结点路径,上的所有结点都是这个结点的祖先结点。
10.子孙结点(Descendant):某- - 结点的子树中的所有结点是这个结点的子孙。
11.结点的层次(Level) :规定根结点在1层,其它任一结点的层数是其父结点的层数加1。.
12.树的深度(Depth) :树中所有结点中的最;大层次是这棵树的深度。,
二叉树的定义
二叉树T: 一个有穷的结点集合。
这个集合可以为空
若不为空,则它是由根结点和称为其左子树T[和右子树TR的
两个不相交的二叉树组成。
树的存储结构
typedef struct TreeNode *BinTree;
typedef BinTree Position;
struct TreeNode{
ElementType Data;
BinTree Left; ;
BinTree Right;
}
二叉树的遍历
(1)先序遍历
遍历过程为:
①访问根结点;
②先序遍历其左子树;
③先序遍历其右子树。
void PreOrderTraversal ( BinTree BT )
{
if(BT){
printf ("%d", BT->Data) ;
PreOrderTraversal( BT->Left ) ;
PreOrderTraversal( BT->Right ) ;
}
}
(2)中序遍历
遍历过程为:
①中序遍历其左子树;
②访问根结点;
③中序遍历其右子树。
(3)后序遍历
遍历过程为:
①后序遍历其左子树;
②后序遍历其右子树;
③访问根结点。
二叉树的非递归遍历
*中序遍历非递归遍历算法
非递归算法实现的基本思路:使用堆栈
中序遍历非递归遍历算法
➢遇到一个结点,就把它压栈,并去遍历它的左子树;
当左子树遍历结束后,从栈项弹出这个结点并访问它;
➢然后按其右指针再去中序遍历该结点的右子树
void InOrderTraversal ( BinTree BT )
{
BinTree T = BT ;
Stack S = CreatStack( MaxSize ); /*创建 并初始化堆栈S*/.
while( T | ! IsEmpty(S) ) { //树不空或堆栈不空
while(T){ /*一直向左 并将沿途结点压入堆栈*/
Push(S,T) ; //第一次碰到结点,先序遍历非递归只需把Print移动到此处即可
T = T->Left;
}
if(!IsEmpty(S)) {
T = Pop(S); /*第二次碰到节点,结点弹出堆栈*/
printf("%5d", T->Data); /* (访问)打印结点*/
T = T->Right; /*转向右子树*/
}
}
}
层序基本过程:先根结点入队,然后:
①从队列中取出一个元素;
②访问该元素所指结点;
③若该元素所指结点的左、右孩子结点非空,
则将其左、右孩子的指针顺序入队。
void LevelOrderTraversal ( BinTree BT )
{
QueueQ;
BinTree T;
if ( !BT ) return; /*若是空树则直接返回*/
Q = CreatQueue( MaxSize ); /*创建并初始化队列Q*/
AddQ(Q,BT);
while ( !IsEmptyQ( Q ) ) {
T = DeleteQ(Q ) ;
printf ("&d\n", T->Data); /*访 问取出队列的结点*/
if ( T->Left )
AddQ( Q,T->Left ) ;
if ( T->Right )
AddQ( Q,T->Right ) ;
}
}
什么是二叉搜索树
二叉 搜索树,(BST, Binary Search Tree),
也称二叉排序树或二叉查找树
二叉搜索树:一棵二叉树,可以为空;如果不为空,满足以下性质:
1.非空左子树的所有键值小于其根结点的键值。
2.非空右子树的所有键值大于其根结点的键值。
3.左、右子树都是二叉搜索树。
二叉搜索树的查找操作Find
Position Find( ElementType X,BinTree BST ){
if( !BST ) return NULL; /*查找失败*/
if( X > BST->Data )
return Find( X, BST->Right ); /*在右子树中继续查找*/
else if( X < BST->Data )
return Find( x, BST->Left ); /*在左子树中继续查找*/
else /* X == BST->Data */
return BST; /*查找成功,返回结点的找到结点的地址*/
}
由于非递归函数的执行效率高,
可将“尾递归”函数改为迭代函数
Position IterFind( ElementType X,BinTree BST )
{
while( BST ) {
if( X > BST->Data )
BST = BST->Right; /*向右子树中移动,继续查找*/
else if( X < BST->Data )
BST = BST->Left; 7*向左子树中移动, 继续查找*/
else /* X == BST->Data */
return BST; /*查找成功,返回结点的找到结点的地址*/
}
return NULL; /*查找失败*/
}
二叉搜索树的插入
[分析]关键是要找到元素应该插入的位置,
可以采用与Find类似的方法
BinTree Insert ( ElementType X,BinTree BST )
{
if( !BST ) {
/*若原树为空, 生成并返回一个结点的二叉搜索树*/
BST = malloc (sizeof (struct TreeNode) ) ;
BST->Data = X;
BST->Left = BST->Right = NULL;
}
else if( X < BST->Data ) /*开始找要插入元素的位置*/
BST->Left = Insert( X,BST->Left) ;
/*递归插入左子树*/ .
else if( X > BST- >Data )
BST->Right = Insert( X, BST->Right) ;
/*递归插入右子树*/ .
/* else x已经存在,什么都不做*/
return BST ;
}
二叉搜索树的删除
考虑三种情况:
1.要删除的是叶结点:直接删除,并再修改其父结点指针---置为NULL
2.要删除的结点只有一个孩子结点 : 将其父结点的指针指向要删除结点的孩子结点
3.要删除的结点有左、右两棵子树 : 用另一结点替代被删除结点:右子树的最小元素或者左子树的最大元素
1、取右子树中的最小元素替代
2、取左子树中的最大元素替代
BinTree Delete ( ElementType X,BinTree BST ){
Position Tmp ;
if( !BST ) printf ("要删除的元素未找到") ;
else if( X <. BST->Data )
BST->Left = Delete( x, BST->Left); /*左子树递归删除*/
else if( X > BST->Data )
BST->Right = Delete( x, BST->Right); /*右子树递归删除*/
else /*找到要删除的结点*/
if( BST->Left && BST->Right ) { /*被删除结点有左右两个子结点*/
Tmp = FindMin( BST->Right ) ;
/*在右子树中找最小的元素填充删除结点*/
BST->Data = Tmp->Data;
BST->Right = Delete( BST->Data, BST->Right) ;
/*在删除结点的右子树中删除最小元素*/
} else { /*被删除结点有一个或无子结点*/
Tmp = BST;
if( !BST->Left ) /* 有右孩子或无子结点*/
BST = BST->Right;
else if( !BST->Right ) /*有左孩子或无子结点*/
BST = BST->Left;
free( Tmp ) ;
}
return BST ;
}
什么是平衡二叉树
“平衡因子( Balance Factor,简称BF) : BF(T) = hu-hr,
其中hu和hR分别为T的左、右子树的高度。
平衡二叉树( Balanced Binary Tree) ( AVL树)
空树,或者任一结点左、右子树高度差的绝对值不超过1,即|BF(T)| <= 1
平衡二叉树的调整
typedef struct AVLNode *Position;
typedef Position AVLTree; /* AVL树类型 */
struct AVLNode{
ElementType Data; /* 结点数据 */
AVLTree Left; /* 指向左子树 */
AVLTree Right; /* 指向右子树 */
int Height; /* 树高 */
};
int Max ( int a, int b )
{
return a > b ? a : b;
}
AVLTree SingleLeftRotation ( AVLTree A )
{ /* 注意:A必须有一个左子结点B */
/* 将A与B做左单旋,更新A与B的高度,返回新的根结点B */
AVLTree B = A->Left;
A->Left = B->Right;
B->Right = A;
A->Height = Max( GetHeight(A->Left), GetHeight(A->Right) ) + 1;
B->Height = Max( GetHeight(B->Left), A->Height ) + 1;
return B;
}
AVLTree DoubleLeftRightRotation ( AVLTree A )
{ /* 注意:A必须有一个左子结点B,且B必须有一个右子结点C */
/* 将A、B与C做两次单旋,返回新的根结点C */
/* 将B与C做右单旋,C被返回 */
A->Left = SingleRightRotation(A->Left);
/* 将A与C做左单旋,C被返回 */
return SingleLeftRotation(A);
}
/*************************************/
/* 对称的右单旋与右-左双旋请自己实现 */
/*************************************/
AVLTree Insert( AVLTree T, ElementType X )
{ /* 将X插入AVL树T中,并且返回调整后的AVL树 */
if ( !T ) { /* 若插入空树,则新建包含一个结点的树 */
T = (AVLTree)malloc(sizeof(struct AVLNode));
T->Data = X;
T->Height = 0;
T->Left = T->Right = NULL;
} /* if (插入空树) 结束 */
else if ( X < T->Data ) {
/* 插入T的左子树 */
T->Left = Insert( T->Left, X);
/* 如果需要左旋 */
if ( GetHeight(T->Left)-GetHeight(T->Right) == 2 )
if ( X < T->Left->Data )
T = SingleLeftRotation(T); /* 左单旋 */
else
T = DoubleLeftRightRotation(T); /* 左-右双旋 */
} /* else if (插入左子树) 结束 */
else if ( X > T->Data ) {
/* 插入T的右子树 */
T->Right = Insert( T->Right, X );
/* 如果需要右旋 */
if ( GetHeight(T->Left)-GetHeight(T->Right) == -2 )
if ( X > T->Right->Data )
T = SingleRightRotation(T); /* 右单旋 */
else
T = DoubleRightLeftRotation(T); /* 右-左双旋 */
} /* else if (插入右子树) 结束 */
/* else X == T->Data,无须插入 */
/* 别忘了更新树高 */
T->Height = Max( GetHeight(T->Left), GetHeight(T->Right) ) + 1;
return T;
}