一、栈与队列
10.1-2 说明如何在一个数组A[1..n]中实现两个栈,使得当两个栈的元素个数之和不为n时,两者都不会发生上溢。要求PUSH和POP操作的运行时间为O(1)。
把数组的两端作为栈底,在入栈时向中间靠近。
10.1-6 如何用两个栈实现一个队列。
两个栈:S1,S2。
入队:向A栈入栈。
出队:若S2栈不为空,则从S2栈中出栈;
若S2栈为空,S1栈不空,则从S1栈中把元素全部倒入S2栈(即S1栈元素依次出栈,并入S2栈)。
若S2栈为空,S1栈为空,则栈空。
出队与入队的时间复杂度为O(1)。
10.1-7 如何用两个队列实现一个栈。
两个队列:Q1,Q2。
入栈:向Q1,Q2中非空的一方入队;若都为空则Q1,Q2都可。
出栈:若Q1非空,将Q1中元素(除队尾元素)依次出队,并入Q2。将Q1中队尾元素出队即出栈元素。
若Q2非空,操作反向。
入栈O(1),出栈O(n)。
二、链表
10.2-1 单链表上的动态集合操作INSERT与DELETE操作能否在O(1)时间内实现。
若指定插入位置:O(n),若指定删除的值:O(n),因为需要遍历查询操作。
若指定在节点node后插入:O(1)。在指定节点node前插入:O(1),在node后插入,然后交换node与插入节点的key。
若删除指定节点node的后继O(1)。
若指定删除节点node:O(1),交换node与其后继的key,然后删除后继。
若删除指定节点node的前驱O(n),需要遍历。
10.2-2 用单链表L实现一个栈,要求PUSH与POP时间为O(1)。
入栈时,从表头插入。
出栈时,第一个元素出栈。
10.2-3 用单链表L实现一个队列,ENQUEUE和DEQUEUE时间为O(1)。
入栈时,从表尾插入。
出栈时,第一个元素出栈。
10.2-4 链表的查找过程每次循环需要两个测试:一是检查x!=NULL,二是检查x.key!=k。如何省略x!=NULL。
将哨兵的key置为x,在循环结束以后验证x是否是哨兵。
10.2-7 给出一个O(n)的非递归,实现对n个元素的单链表逆转,只能使用固定大小的存储空间。
定义一个新的头节点head‘,指向第一个元素。
将原头结点的后继置为NULL。
将新的链表head',从表头插入head。
一次循环O(n),一个头节点O(1)。
10.2-8 如何在每个元素仅使用一个指针x.np(而不是通常的两个指针next和prev)的情况下实现双向链表。
假设所有指针的值都可视为k位的整型数,且定义x.np = x.next XOR x.prev,即x.next和x.prev的k位异或。(NIL的值用0表示)
头节点head.next = head.prev(NIL) XOR head.np,因为head.prev=NIL为零,且head.np已知,因此可以得到head.next,
则可以依次得到1...n节点的信息: x.next = x.np XOR x.prev
x.prev = x.np XOR x.next
Search操作:需要遍历:依次计算x.next并比较x.key
Insert操作:...
Delete:...
如何在O(1)时间内实现逆转
三、指针和对象的实现
对象的多重数组表示:
<pre name="code" class="cpp">ALLOCATE-OBJECT()
if free == NIL
error "out of space"
else x = free
free = x.next
return x
FREE-OBJECT(x)
x.next=free
free=x
10.3-4 紧凑的多重数组。
过程类似于一个数组实现两个栈。
假设表本身是紧凑的,有n个元素。
ALLOCATE-OBJECT()
栈顶元素加1,并把第n+1个空间拿出来。
FREE-OBJECT
若删除的是第n个元素,栈顶元素减1即可。
若删除的是[1..n-1]元素,假设是第k个,则在删除该元素后,将栈顶元素置于之前的空位。
然后修改k-1的next与k+1的prev,并且修改n-1的next。
( L[k-1].next = k+1;
L[k+1].prev = k-1;
L[n-1].next = k; )
10.3-5 设L是一长度为n的双链表,存储在长度为m的数组key、next和prev中。假设这些数组由维护双链自由表F的两个过程ALLOCATE-OBJECT和FREE-OBJECT来操纵。进一步假设在数组的m个元素中,有n个在表L上和有m-n个在自由表F上,移动L中的元素,使他们占有数组中的1, 2, ..., n位置,同时调节自由表F使之保持正确,并占有数组位置n+1, n+2, ..., m。所给出的运行时间应该是Θ(n),且只能使用固定量的额外空间。
依次交换L与数组M。假设数组为M。
</pre><pre name="code" class="cpp"><pre name="code" class="cpp">if v1.prev != null
v1.prev.next = v2;
if v2.prev != null
v2.prev.next = v1;
if v2.next != null
v2.next.prev = v1;
temp = v1.key;
v1.key = v2.key;
v2.key = temp;
}