堆栈(Stack)
- Stack CreateStack( int MaxSize ): 生成空堆栈,其最大长度为MaxSize
- int IsFull( Stack S, int MaxSize ):判断堆栈S是否已满
- void Push( Stack S, ElementType item ):将元素item压入堆栈
- int IsEmpty ( Stack S ):判断堆栈S是否为空
- ElementType Pop( Stack S ):删除并返回栈顶元素
eg:计算机如何进行表达式求值? 中缀表达式:运算符号位于两个运算数之间。如 ,a + b * c - d / e 后缀表达式:运算符号位于两个运算数之后。如, a b c * + d e / -
堆栈的其他应用: 函数调用及递归实现 深度优先搜索 回溯算法
线性表(Linear List)
- List MakeEmpty():初始化一个空线性表L;
- ElementType FindKth( int K, List L ):根据位序K,返回相应元素 ;
- int Find( ElementType X, List L ):在线性表L中查找X的第一次出现位置;
- void Insert( ElementType X, int i, List L):在位序i前插入一个新元素X;
- void Delete( int i, List L ):删除指定位序i的元素;
- int Length( List L ):返回线性表L的长度n。
eg: 多项式表示? 链表结构存储非零项 链表中每个结点存储多项式中的一个非零项,包 括系数和指数两个数据域以及一个指针域
- 插入(在第 i-1(1≤i≤n+1)个结点后插入一个值为X的新结点) (1)先构造一个新结点,用s指向; (2)再找到链表的第 i-1个结点,用p指向; (3)然后修改指针,插入结点 ( p之后插入新结点是 s)
- 删除(删除链表的第 i (1≤i≤n)个位置上的结点) (1)先找到链表的第 i-1个结点,用p指向; (2)再用指针s指向要被删除的结点(p的下一个结点); (3)然后修改指针,删除s所指结点; (4)最后释放s所指结点的空间。
广义表(Generalized List) 广义表是线性表的推广 对于线性表而言, n个元素都是基本的单元素; 广义表中,这些元素不仅可以是单元素也可以是另一个广义表。
多重链表:链表中的节点可能同时隶属于多个链 多重链表中结点的指针域会有多个,如前面例子包含了Next和 SubList两个指针域; 但包含两个指针域的链表并不一定是多重链表,比如在双向链表 不是多重链表。 多重链表有广泛的用途: 基本上如树、图这样相对 复杂的数据结构都可以采 用多重链表方式实现存储。
队列(Queue)
- Queue CreatQueue( int MaxSize ):生成长度为MaxSize的空队列;
- int IsFullQ( Queue Q, int MaxSize ):判断队列Q是否已满;
- void AddQ( Queue Q, ElementType item ): 将数据元素item插入队列Q中;
- int IsEmptyQ( Queue Q ): 判断队列Q是否为空;
- ElementType DeleteQ( Queue Q ):将队头数据元素从队列中删除并返回。
队列的顺序存储结构通常由一个一维数组和一个记录队列头元 素位置的变量front以及一个记录队列尾元素位置的变量rear组成
eg: 顺环队列 工作队列 队列的链式
树
静态查找:集合中记录是固定的 没有插入和删除操作,只有查找 动态查找:集合中记录是动态变化的 除查找,还可能发生插入和删除
静态查找 顺序查找 二分查找(Binary Search)
int BinarySearch ( StaticTable * Tbl, ElementType K){
/*在表Tbl中查找关键字为K的数据元素*/
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; /*调整右边界*/
else if( K > Tbl->Element[mid]) left = mid+1; /*调整左边界*/
else return mid; /*查找成功,返回数据元素的下标*/
}
return NotFound; /*查找不成功,返回-1*/
}
判定树上每个结点需要的查找次数刚好 为该结点所在的层数; 查找成功时查找次数不会超过判 定树的深度 n个结点的判定树的深度 为[log2n]+1
基本术语 结点的度(Degree):结点的子树个数 树的度:树的所有结点中最大的度数 结点的层次(Level):规定根结点在1层, 其它任一结点的层数是其父结点的层数加1。 树的深度(Depth):树中所有结点中的最 大层次是这棵树的深度。
二叉树T 一个有穷的结点集合。 这个集合可以为空 若不为空,则它是由根结点和称为其左子树TL和右子树TR的 两个不相交的二叉树组成。
斜二叉树 每一层都只有一个结点 完全二叉树: 有n个结点的二叉树,对树中结点按 从上至下、从左到右顺序进行编号, 编号为i(1 ≤ i ≤ n)结点与满二叉树 中编号为 i 结点在二叉树中位置相同 满二叉树, 完美二叉树 2**n - 1
一个二叉树第 i 层的最大结点数为:2 深度为k的二叉树有最大结点总数为: 2 k -1,k 大于等于 1。 对任何非空二叉树 T,若n0表示叶结点的个数、n2是 度为2的非叶结点个数,那么两者满足关系n0 = n2 +1。
1、Boolean IsEmpty( BinTree BT ): 判别BT是否为空; 2、void Traversal( BinTree BT ):遍历,按某顺序访问每个结点; 3、BinTree CreatBinTree( ):创建一个二叉树。
遍历 先序遍历 根 左 右 中序遍历 左 根 右 后序遍历 左 右 根 非递归算法实现的基本思路:使用堆栈 层序遍历 队列实现:遍历从根结点开始,首先将根结点入队,然后开始执 行循环:结点出队、访问该结点、其左右儿子入队
二叉搜索树(BST,Binary Search Tree) 二叉搜索树:一棵二叉树,可以为空;如果不为空,满足以下性质:
- 非空左子树的所有键值小于其根结点的键值。
- 非空右子树的所有键值大于其根结点的键值。
- 左、右子树都是二叉搜索树。
Position Find( ElementType X, BinTree BST ):从二叉搜索树BST 中查找元素X,返回其所在结点的地址; Position FindMin( BinTree BST ):从二叉搜索树BST中查找并返回 最小元素所在结点的地址; Position FindMax( BinTree BST ) :从二叉搜索树BST中查找并返回 最大元素所在结点的地址。 BinTree Insert( ElementType X, BinTree BST ) BinTree Delete( ElementType X, BinTree BST )
最大元素一定是在树的最右分枝的端结点上 最小元素一定是在树的最左分枝的端结点上
平衡二叉树(Balance Factor,简称BF) 平衡二叉树(Balanced Binary Tree)(AVL树) 空树,或者 任一结点左、右子树高度差的绝对值不超过1,即|BF(T) |≤ 1
堆(heap) 特殊的“队列”,取出元素的顺序是 依照元素的优先权(关键字)大小,而不是元素进入队列的先后顺序
堆的两个特性 结构性:用数组表示的完全二叉树; 有序性:任一结点的关键字是其子树所有结点的最大值(或最小值) “最大堆(MaxHeap)” ,也称“大顶堆”:最大值 “最小堆(MinHeap)” ,也称“小顶堆” :最小值
最大堆(MaxHeap) 数据对象集:完全二叉树,每个结点的元素值不小于其子结点的元素值
MaxHeap Create( int MaxSize ):创建一个空的最大堆。 Boolean IsFull( MaxHeap H ):判断最大堆H是否已满。 Insert( MaxHeap H, ElementType item ):将元素item插入最大堆H。 Boolean IsEmpty( MaxHeap H ):判断最大堆H是否为空。 ElementType DeleteMax( MaxHeap H ):返回H中最大元素(高优先级)。
// 插入
void Insert( MaxHeap H, ElementType item ){ /* 将元素item 插入最大堆H,其中H->Elements[0]已经定义为哨兵 */
int i;
if ( IsFull(H) ) {
printf("最大堆已满");
return;
}
i = ++H->Size; /* i指向插入后堆中的最后一个元素的位置 */
for ( ; H->Elements[i/2] < item; i/=2 )
H->Elements[i] = H->Elements[i/2]; /* 向下过滤结点 */
H->Elements[i] = item; /* 将item 插入 */
}
// 删除
ElementType DeleteMax( MaxHeap H ) { /* 从最大堆H中取出键值为最大的元素,并删除一个结点 */
int Parent, Child;
ElementType MaxItem, temp;
if ( IsEmpty(H) ) {
printf("最大堆已为空");
return;
}
MaxItem = H->Elements[1]; /* 取出根结点最大值 */
/* 用最大堆中最后一个元素从根结点开始向上过滤下层结点 */
temp = H->Elements[H->Size--];
for( Parent=1; Parent*2<=H->Size; Parent=Child ) {
Child = Parent * 2;
if( (Child!= H->Size) &&
(H->Elements[Child] < H->Elements[Child+1]) )
Child++; /* Child指向左右子结点的较大者 */
if( temp >= H->Elements[Child] ) break;
else /* 移动temp元素到下一层 */
H->Elements[Parent] = H->Elements[Child];
}
H->Elements[Parent] = temp;
return MaxItem;
}
建立最大堆:将已经存在的N个元素按最大堆的要求存放在 一个一维数组中 方法1:通过插入操作,将N个元素一个个相继插入到一个初 始为空的堆中去,其时间代价最大为O(N logN)。 建立最大堆:将已经存在的N个元素按最大堆的要求存放在 一个一维数组中 方法2:在线性时间复杂度下建立最大堆。 (1)将N个元素按输入顺序存入,先满足完全二叉树的结构特性 (2)调整各结点位置,以满足最大堆的有序特性。