假设有一带头结点的循环双链表表示的线性表L=(a
1
,a
2
,…,a
n-1
,a
n
)。
设计在时间和空间上都尽可能高效的算法,将线性表L改造成L=(a
1
,a
3
,…,a
n
,…,a
4
,a
2
)。要求:
问答题
给出算法的基本设计思想。
【正确答案】正确答案:基本设计思想:从改造后的线性表L可以看出,前部分结点为奇序号结点,并且递增;后部分结点为偶序号结点,并且递减。所以可以考虑建立两个新的循环双链表,一个带头结点的循环双链表L(由原先的L改造而来),保存原先线性表L的奇数号结点,可以采取尾插法,让其序号顺序递增;而另外一个不带头结点的循环双链表s,保存原先线性表L的偶数号结点,可以采取头捅法,让其序号顺序递减。最后,将L和s两个循环双链表连接成一个循环双链表L,并且L为其头结点指针。
【答案解析】
问答题
根据设计思想,采用C或C++或Java语言描述算法,关键之处给出注释。
【正确答案】正确答案:算法实现如下: void modify(struct node*head) { s.truct node *s=NULL; struct node *L=head; st ruct node *p=L->next,*p1; L->next=L->preV=NULL; for(;p!=L;p=p1) { if(p->next !=L) { //删除偶数结点 p1=p->next; p->next=p1->next; p1->next->prev=p; //把偶数结点插入s if(s==NULL) { s=p1; p1->next=p1->prev=p1; } else { p1->next=s; p1->prev=s->prev; s->prev->next=p1; s->prev=p1; s=s->prey; } } p1=p->next; L->prey->next=p; p->next=L; p->prev=L->prey; L->prev=p; } //合并两个链表 if(s==NULL)return; p=s->prev p->next=L; L->prev->next=s; s->prev=L->prev; L->prev=p; }
【答案解析】
问答题
说明你所设计算法的时间复杂度与空间复杂度。
【正确答案】正确答案:空间复杂度分析:除去链表本身的空间外,额外的空间消耗为O(1)。其实本题可以看成是原来链表的重新组合,并没有开辟新的空间。 时间复杂度分析:整个过程相当于把链表遍历了一遍,所以时间复杂度为O(n)。
【答案解析】