文档库 最新最全的文档下载
当前位置:文档库 › 数据结构相关难点

数据结构相关难点

问题:对链表设置头结点的作用是什么?



解答:

其好处有:

(1) 对带头结点的链表,在表的任何结点之前插入结点或删除表中任何结点,所要做的都是修改前一结点的指针域,因为任何元素结点都有前驱结点。若链表没有头结点,则首元素结点没有前驱结点,在其前插入结点或删除该结点时操作会复杂些。

(2) 对带头结点的链表,表头指针是指向头结点的非空指针,因此空表与非空表的处理是一样的。


问题:何为队列上溢现象?何为假溢现象?有哪些解决方法?并分别简述其工作原理。



解答:

在队列的顺序存储结构中,设队头指针为front,队尾指针为rear,队的容量为MaxSize。当有元素要加入队列时,若rear=MaxSize(初始时rear=0),则发生队列的上溢现象,该元素不能加入队列。

队列的假溢出现象是指队列中还有空余的空间,但元素不能进队列。造成这种现象的原因是由于队列的操作方式所致。

解决队列假溢出的方法如下:

(1)建立一个足够大的存储空间,但这样做会造成空间浪费。

(2)采用环形队列方式。

(3)采用平移元素的方法,当删除一个对头元素时,依次移动队中的元素,始终使front指向队列中的第一个位置。



问题:若使用循环链表来表示队列,p是链表中的一个指针.试基于此结构给出队列的插入(enqueue)和删除(dequeue)算法,并给出p为何值时队列空.



解答:

链式队列的类定义

template class Queue; //链式队列类的前视定义

template class QueueNode { //链式队列结点类定义

friend class Queue;

private:

Type data; //数据域

QueueNode *link; //链域

QueueNode ( Type d = 0, QueueNode *l = NULL ) : data (d), link (l) { } //构造函数

};



template class Queue { //链式队列类定义

public:

Queue ( ) : p ( NULL ) { } //构造函数

~Queue ( ); //析构函数

void EnQueue ( const Type & item ); //将item加入到队列中

Type DeQueue ( ); //删除并返回队头元素

Type GetFront ( ); //查看队头元素的值

void MakeEmpty ( ); //置空队列,实现与~Queue ( ) 相同

int IsEmpty ( ) const { return p == NULL; } //判队列空否

private:

QueueNode *p; //队尾指针(在循环链表中)

};



template Queue::~Queue ( ) { //队列的析构函数

QueueNode *s;

while ( p != NULL ) { s = p; p = p→link; delete s; } //逐个删除队列中的结点

}



//队列的插入函数

template void Queue::EnQueue ( const Type & item ) {

if ( p == NULL ) { //队列空, 新结点成为第一个结点

p = new QueueNode ( item, NULL ); p→link = p;

}

el

se { //队列不空, 新结点链入p之后

QueueNode *s = new QueueNode ( item, NULL );

s→link = p→link; p = p→link = s; //结点p指向新的队尾

}

}



//队列的删除函数

template Type Queue::DeQueue ( ) {

if ( p == NULL ) { cout << "队列空, 不能删除!" << endl; return 0; }

QueueNode *s = p; //队头结点为p后一个结点

p→link = s→link; //重新链接, 将结点s从链中摘下

Type retvalue = s→data; delete s; //保存原队头结点中的值, 释放原队头结点

return retvalue; //返回数据存放地址

}


问题:二叉排序树的删除



解答:

二叉排序树在删除时分三种情况:删除叶子、删除度为1的节点和删除度为2的节点。删除叶子,比较简单,直接删除就可以了。关键删除度为1的节点,要很清楚由其儿子节点代替。一般来说,初学者会认为删除度为2的点较难掌握,其实,只要掌握删除度为1的做法,删除度为2的可以转化为删除度为1的情况。我们在讲义中提到“替身”的概念。用替身替代被删除点,就可以转化为删除度为1的情况了。


问题:哈希的平均查找长度



解答:

查找成功的平均查找长度:

成功地找到某一个 key 所需要的探测次数恰等于将这个 key 插入到散列表中所需要的探测次数。




问题:快速排序算法的程序实现



解答:

教材在实现快速排序时,首先选择一个关键字作为界点(第一个元素、中间位置元素和最后元素选择中间值元素作为界点),防止出现算法的最坏情况。

程序中,算法的关键在于

while ( arr[++k]
while ( arr[--j]>milestone );//从右开始寻找小于界点的元素

if (k
另外,快速排序算法还有其他的实现方法,比如清华严蔚敏教材的实现方法通常称为填空穴的方法。不同的方法实现的中间结果序列可能不同,但是,时间和空间性能是相同的。


问题:堆排序时间复杂性分析



解答:

分成两个部分,即初始化部分和排序部分。

在初始化的时间部分:

第 i 层上小堆的个数=第 i 层上结点的个数 = 最多 2i-1

第 i 层上小堆的高度 = h-i+1

建第 i 层上每个小堆最多所需的比较次数 = 2×(h-i)次



(1)∑j/2j< 2

(2)log(n-1)!与nlogn 同数量级有所了解。



问题:Dijktra 算法的时间复杂性的推导

在采用最小化堆挑选最短边的情况下。时间复杂性的级别 O((n+e) logn)正确吗?



解答:

1.建堆代价:O(n)

2.堆中的所有结点,都将会输出。输出一个,堆都会进行调整。代价为: O(nLogn)

3.见 NO. 41 第 7 行

,某个d[i] 的值可能变小,如何进行调整,使堆仍为最小化堆?由此可推出 Dijktra 算法的时间复杂性为:O((n+e)Logn)

4.Prim 算法如用最小化堆实现,问题类似。

5.相关问题:如最小化堆中的结点变大或变小,如何修改,使其仍能为最小化堆。




问题:深度优先判断有向图G中顶点i到顶点j是否有路径



解答:

int visited[MAXSIZE]; //指示顶点是否在当前路径上

int exist_path_DFS(ALGraph G,int i,int j)//深度优先判断有向图G中顶点i到顶点j是否有路径,是则返回1,否则返回0

{

if(i==j) return 1; //i就是j

else

{

visited[i]=1;

for(p=G.vertices[i].firstarc;p;p=p->nextarc)

{

k=p->adjvex;

if(!visited[k]&&exist_path(k,j)) return 1;//i下游的顶点到j有路径

}//for

}//else

}//exist_path_DFS



问题:非递归遍历强连通图G



解答:

分析:本算法的基本思想与二叉树的先序遍历非递归算法相同,由于是强连通图,所以从第一个结点出发一定能够访问到所有结点.



void STraverse_Nonrecursive(Graph G)

{

int visited[MAXSIZE];

InitStack(S);

Push(S,GetVex(S,1)); //将第一个顶点入栈

visit(1);

visited=1;

while(!StackEmpty(S))

{

while(Gettop(S,i)&&i)

{

j=FirstAdjVex(G,i);

if(j&&!visited[j])

{

visit(j);

visited[j]=1;

Push(S,j); //向左走到尽头

}

}//while

if(!StackEmpty(S))

{

Pop(S,j);

Gettop(S,i);

k=NextAdjVex(G,i,j); //向右走一步

if(k&&!visited[k])

{

visit(k);

visited[k]=1;

Push(S,k);

}

}//if

}//while

}//Straverse_Nonrecursive




问题:判断邻接表方式存储的有向图G的顶点i到j是否存在长度为k的简单路径



解答:

int visited[MAXSIZE];

int exist_path_len(ALGraph G,int i,int j,int k)//

{

if(i==j&&k==0) return 1; //找到了一条路径,且长度符合要求

else if(k>0)

{

visited[i]=1;

for(p=G.vertices[i].firstarc;p;p=p->nextarc)

{

l=p->adjvex;

if(!visited[l])

if(exist_path_len(G,l,j,k-1)) return 1; //剩余路径长度减一

}//for

visited[i]=0; //本题允许曾经被访问过的结

点出现在另一条路径中

}//else

return 0; //没找到

}//exist_path_len










//队空条件 p == NULL.

相关文档