1.在线性表的下列存储结构中,读取元素花费时间最少的是 顺序表(随机存取,有下标,单链表,双向链表,循环链表必须从头结点开始依次顺序往下找,)
2.顺序表示线性表的顺序存取结构
3.说法纠正:
线性表的数据元素可以是数字、字符、记录等不同类型
线性表包含的数据元素个数不是任意的
线性表根据存储结构可以分为顺序表(数组实现,静态的)、链表(动态就是链式存储结构)
存在这样的线性表、表中各结点都没有直接前驱和直接后继
4.在顺序表中,只要知道 基地址 就可在相同时间内求出任一结点的存储地址
5.在等概率情况下,顺序表的插入操作要移动一半结点 二分之(n-1)
6.在根据序号查找,使用线性表比使用链表好
7.在一个具有n个结点的有序单链表中插入一个新结点并井然有序的时间复杂度是 O(n)
插入就是O(1),关键是找到位置,从头结点找位置是O(n)
8.循环链表适合经常在首尾两端操作线性表的存储结构
循环链表,经常在首尾两端做操作,只要有一个结点,从可以找到首尾
双向链表不能记录首尾
9.非空的循环单链表head的尾节点(由r所指向)满足 r->next = head
10.设线性表(a1,a2,a3......an)按顺序存储,且每个字节占有m个存储单元,则元素地址为
LOC(a1)+(i-1)*m 其中LOC(a1)表示元素a1的地址
11.线性表如果采用链式存储的话,要求内存中可用存储单元的地址 不一定是连续的
13.P之后插入S结点,则执行 S-> next = P-next;p-next=S
14.在单链表中,不能从任意结点出发访问到表中所有结点
习题1 假设用两个一维数组L[1...n],R[1...n]作为有n个结点的二叉树的存储结构,分别指示结点i的左孩子和右孩子,0表示空。试编写算法判别结点n是否是结点v的子孙
分析: L 20507000
R 34608000
LR存放左孩子和右孩子
用队列,3(v)的左孩子和右孩子(5和6)入队列,然后出队列5看是否等于u
当队列空的时候都没有元素和u相等,说明不是子孙,相当于把二叉树按层次遍历。依次入队列。
设置一个队列,初始化为结点v(即结点v入队列)循环:当队列非空,即对头元素出队列,DeQueue(Q,e) 如果e=u,则u是v的子孙,否则,e的左孩子,右孩子分别入队列,重复循环
算法:Status exercise(L,R,u,v)
{
//R[i],L[i]分别存放二叉树的第i个结点的左、右孩子,判断u是否是v的子孙;如是,返回OK,否则返回ERROR
IniQueue(Q),EnQueue(Q,v) //初始化一个Q,初始化之后把v入队列
While(!QueueEmpty(Q))// Q非空
{
DeQueue(Q,e);//e出队列
if e=u return OK;
else {if l[e]<>0 EnQueue(Q,L[e])}//不等于0,入队列,左孩子右孩子入队列
if R[e]<>0 EnQueue(Q,R[e])
}
return ERROR;
}//循环结束了,表示队列空了
暗示了一个层次遍历的过程
.习题二:条件同上,先由L和R建立一维数组T[1....n],,使T中第I个分量知识结点i的双亲,然后编写算法判别结点u是否为结点v的子孙
分析:
1 2 3 4 5 6 7 8 二叉树: 1
L 2 0 5 0 7 0 0 0 2 3
R 3 4 6 0 8 0 0 0 4 5 6
T 0 1 1 2 3 3 5 5 7 8
反过来找双亲v=2,u=8; T[8]=5;T[5]=3;T[3]=1,都没有等于v,则v不是u的双亲
习题三 层次遍历二叉树(实际上就是用队列实现的)
A
B D
C G H
E F
Status exercise_6.47(BiTree T,Status(*Visit)TElemType e)
IniQueue(Q);//初始化队列
if(T) EnQueue(Q,T); //T不空,根节点入队列
while(!QueueEmpty(Q))//队列不空
{
DeQueue(Q,p);//队头元素出队列
Visit(p->data);//访问数据
if(p->lchild)EnQueue(Q,p->lchild);//左孩子和右孩子分别入队列
if(p->rchild)EnQueue(Q,p->rchild);
}
//队列FIFO
习题四 判断给定的一颗二叉树是否是完全二叉树,分析两种存储方式下判断方法:顺序存储;二叉链表存储
分析:
二叉树
A
B I
C G H J
D
顺序存储(顺序必须是:A左孩子右孩子):ABI CG HJ 0D(没有就补充0)
i
2i 2i+1
把后边的分量全部遍历一下是不是都是0.才能肯定是不是都是0
满二叉树和完全二叉树适合用顺序表存储
1.如果某结点左孩子不存在,但是右孩子存在,则必然不是完全二叉树
2.如果某结点的左右孩子不存在,则此后每一个节点的都不应该存在孩子节点,否则必然不是完全二叉树
3.如果某结点左孩子存在,但右孩子不存在,则此后的每一个结点也应该不存在孩子节点,否则不是完全二叉树
算法:
Status exercise_6.49(BiTree T,)
{
//若二叉树T为完全二叉树返回TRUE,否则返回FALSE
IniQueue(Q);tag=1;
if(T)EnQueue(Q,T);//根节点入队列
while(!QueueEmpty(Q)&&tag)//Q不空并且tag=1
{
DeQueue(Q,p);//对头元素出队列
if(p->lchild)
{
//如果lchild存在,就把lchild入队列
EnQueue(Q,P->lchild);
if(p->rchild)EnQueue(Q,p->rchild) //如果右孩子存在,(在左孩子存在的情况下)右孩子入队列
else tag=0;//else如果左孩子存在,但是右孩子不存在,tag=0(表示遇到了警戒情况
}
else{tag=0;//左孩子不存在 tag=0
if(p->rchild) return FALSE;}//左孩子不存在但是右孩子存在,返回FALSE
}//while 上述对应12情况
//如果tag=0退出了循环,则遇到了警戒情况
While(!QueueEmpty(Q))//队列是不是空的,如果不空,就出队列
{
DeQueue(Q,p);
if((p->lchild)||(p->rchild))return FALSE;//左孩子和右孩子存在
}
return TRUE;//第二个循环用来判断剩下的元素是不时存在左孩子和右孩子
}
//基于层次遍历的结点
习题五 假设在二叉链表中增设两个域:双亲域指示双亲结点;标志语域(mark取值0--2)以区分在遍历过程中到达该结点时应该向左,向右或访问该结点,试以此存储结构编写不同的栈的后序遍历算法
分析:每一个节点的mark初始化为0
mark=0 则访问左子树,同时mark变为1
1 则访问右子树,同时mark变为2
2 访问根节点
-
+ /
a X
Status exercise(BiTree T,){
//后序遍历二叉树,二叉树的结点有五个域,data,parent,lchild,rchild,mark;mark初始化为0
P=T;//P初始化为根节点
while(P)
{
switch(p->mark){
case 0:
p->mark=1;
if(p->lchild)p=p->lchild;break;
case 1:
p->mark=2;
if(p->rchild)p=p->rchild;break;
case 2:
p->mark=0;visit(P);
p=p->parent;break;
default;
}