题目出处:http://blog.rainbud.net/article/entry20050928-014721
给定一单链表的表头指针和指向其中一个节点的指针,要求以该指针为头将原链表逆序排列,例如:
1. N1->N2->N3->N4->N5->NULL pHEAD = N1,pSTART = N3,返回N3->N2->N1->N5->N4->NULL
2. N1->N2->N3->N4->N5->NULL pHEAD = N1,pSTART = N5,返回N5->N4->N3->N2->N1->NULL
3. N1->N2->N3->N4->N5->NULL pHEAD = N1,pSTART = N1,返回N1->N5->N4->N3->N2->NULL
不允许额外分配存储空间,不允许递归,可以使用临时变量。
很容易想到的做法是先将整个链表逆序,然后将尾节点连接到头节点,然后再从pSTART后面断开。我是把它分成两个部分,即包括pSTART的前面部分和不包括pSTART的后面部分。当pSTART和pHEAD重合时,前面一部分只有一个节点;当pSTART是链表的尾节点的时候,后面一部分是空链表。分别逆序完了以后,再连接起来。
前面有道题说了,使用pHead和两个临时变量就可以将一个链表逆序,我这里没有使用phead,所以用到了三个临时变量。里面用的临时变量比较多,思路不太清晰。
#i nclude
<
iostream
>
#i nclude < string >
using namespace std;
struct Node
{
char name[ 3 ];
Node * next;
Node( const char * p)
{
strcpy(name,p);
next = 0 ;
}
};
// 将某个链表逆序
void ReserseList(Node *& pHead, Node *& pTail)
{
Node * p1 = pHead;
if (p1 == 0 ) // 首指针为空,表示空链表
{
pTail = 0 ;
return ;
}
Node * p2 = p1 -> next;
if (p2 == 0 ) // 首指针的下一个节点为空,表示只有一个节点
{
pTail = 0 ;
return ;
}
// 至少有两个不为空的节点
Node * p3 = 0 ;
while (p2 != 0 )
{
p3 = p2 -> next;
p2 -> next = p1;
p1 = p2;
p2 = p3;
p3 = 0 ;
}
pHead -> next = 0 ; // 将首节点的next置为0,否则会形成循环链表
pTail = pHead;
pHead = p1;
}
// 分成两个链表,然后再合并
Node * Reserse(Node * pHEAD, Node * pSTART)
{
Node * ptmp1 = pHEAD, * ptmp2 = pSTART;
// 将两表拆开
Node * pHead2 = pSTART -> next;
pSTART -> next = 0 ;
ReserseList(ptmp1,ptmp2); // 逆序前面一部分
Node * ptmp3 = 0 ;
ReserseList(pHead2,ptmp3); // 逆序后面一部分
// 合并
if (ptmp2 == 0 ) // 前面一部分只有一个节点
ptmp1 -> next = pHead2;
else // 前面一部分有一个以上的节点
ptmp2 -> next = pHead2;
return ptmp1;
}
void output(Node * tmp)
{
while (tmp != 0 )
{
cout << tmp -> name << " -> " ;
tmp = tmp -> next;
}
cout << " NULL " << endl;
}
int main()
{
Node * pHEAD = new Node( " N1 " );
Node * p2 = new Node( " N2 " );
Node * p3 = new Node( " N3 " );
Node * p4 = new Node( " N4 " );
Node * p5 = new Node( " N5 " );
pHEAD -> next = p2;
p2 -> next = p3;
p3 -> next = p4;
p4 -> next = p5;
output(pHEAD);
Node * result = Reserse(pHEAD,p4);
output(result);
getchar();
return 0 ;
}
#i nclude < string >
using namespace std;
struct Node
{
char name[ 3 ];
Node * next;
Node( const char * p)
{
strcpy(name,p);
next = 0 ;
}
};
// 将某个链表逆序
void ReserseList(Node *& pHead, Node *& pTail)
{
Node * p1 = pHead;
if (p1 == 0 ) // 首指针为空,表示空链表
{
pTail = 0 ;
return ;
}
Node * p2 = p1 -> next;
if (p2 == 0 ) // 首指针的下一个节点为空,表示只有一个节点
{
pTail = 0 ;
return ;
}
// 至少有两个不为空的节点
Node * p3 = 0 ;
while (p2 != 0 )
{
p3 = p2 -> next;
p2 -> next = p1;
p1 = p2;
p2 = p3;
p3 = 0 ;
}
pHead -> next = 0 ; // 将首节点的next置为0,否则会形成循环链表
pTail = pHead;
pHead = p1;
}
// 分成两个链表,然后再合并
Node * Reserse(Node * pHEAD, Node * pSTART)
{
Node * ptmp1 = pHEAD, * ptmp2 = pSTART;
// 将两表拆开
Node * pHead2 = pSTART -> next;
pSTART -> next = 0 ;
ReserseList(ptmp1,ptmp2); // 逆序前面一部分
Node * ptmp3 = 0 ;
ReserseList(pHead2,ptmp3); // 逆序后面一部分
// 合并
if (ptmp2 == 0 ) // 前面一部分只有一个节点
ptmp1 -> next = pHead2;
else // 前面一部分有一个以上的节点
ptmp2 -> next = pHead2;
return ptmp1;
}
void output(Node * tmp)
{
while (tmp != 0 )
{
cout << tmp -> name << " -> " ;
tmp = tmp -> next;
}
cout << " NULL " << endl;
}
int main()
{
Node * pHEAD = new Node( " N1 " );
Node * p2 = new Node( " N2 " );
Node * p3 = new Node( " N3 " );
Node * p4 = new Node( " N4 " );
Node * p5 = new Node( " N5 " );
pHEAD -> next = p2;
p2 -> next = p3;
p3 -> next = p4;
p4 -> next = p5;
output(pHEAD);
Node * result = Reserse(pHEAD,p4);
output(result);
getchar();
return 0 ;
}