常见的面试题,思路:
<span style="font-size:18px;">/* 链表结点结构 */
struct mylist {
int data;
mylist* middle; // point to arbitrary elem of this list( maybe to itself )
mylist* next; // point to next elem
};</span>
1)在原链表的每个节点后面new一个一样的节点,并链接。这样原链表就变成双倍长,每个节点重复出现一次。即1->2->3变成1->(1)->2->(2)-3->(3)。
括号表示新链表的节点。
2)设置新链表节点的middle指针。
3)断开两个链表,返回新链表。
#include
#include
using namespace std;
/* 链表结点结构 */
struct mylist {
int data;
mylist* middle; // point to arbitrary elem of this list( maybe to itself )
mylist* next; // point to next elem
};
void printList( mylist* pHead ) {
while( pHead ) {
printf("%d\n", pHead ->data );
printf("\t%d\n", pHead ->middle ->data );
pHead = pHead ->next;
}
}
mylist* copyMylist( mylist* pMylist ) {
if( pMylist == NULL )
return NULL;
mylist* p = pMylist;
mylist* pRet; /* 保存复制出来的链表第一个节点 */
/* 1) 遍历原链表,在每个节点后面产生并链接与原来相同(data)的节点。*/
/* 运行完后链表的节点重复出现一次,此时每个第二个重复的节点构成了新链表 */
while( p ) {
mylist* pNew = new mylist;
pNew ->data = p ->data;
pNew ->next = p ->next;
pNew ->middle = NULL;
p ->next = pNew;
p = pNew ->next;
}
pRet = pMylist ->next; /* 设置新链表第一个节点 */
p = pMylist;
mylist* q = p ->next;
/* 2) 设置新链表节点的middle指针 */
while( p ) {
q ->middle = p ->middle ->next;
p = q ->next;
if( p )
q = p ->next;
}
/* 3) 分开两个链表,即重新设置新旧链表每个节点的next域 */
p = pMylist;
q = p ->next;
mylist* pNext;
mylist* qNext;
while( p ->next ) {
if( p ->next ->next == NULL ) // 易漏!判断当前节点p是否是原链表的最后一个节点
{
p ->next = NULL;
break;
}
pNext = q ->next;
qNext = pNext ->next;
p ->next = pNext;
q ->next = qNext;
p = pNext;
q = qNext;
}
return pRet;
}
int main()
{
mylist a,b,c,d;
a.data = 1, b.data = 2, c.data = 3, d.data = 4;
a.next = &b, b.next = &c, c.next = &d, d.next = NULL;
a.middle = &c, b.middle = &d, c.middle = &c, d.middle = &b;
mylist* p = copyMylist( &a );
printf("original list a:\n");
printList( &a );
printf("copied list: \n");
printList( p) ;
return 0;
}