2012年(158)
分类: C/C++
2012-11-19 10:39:33
在水精灵的blog上看到趋势的一道考题"线性链表的倒序排列",如果是双向链表就太简单了不值得一提,难就难在"怎样将单链表倒序排列",这道题很常见,我当初也思考过,得出的结论是"更改单链表节点的指针方向,而不是调换其数据",完整算法如下:
for(
Node *pre=0,*next; head&&(next=head->next,head->next=pre,next);
pre=head,head=next );
抛砖引玉,看看有没有更好的算法,或更简洁的代码。
完整的测试代码如下:
#include
#include
using namespace
std;
struct Node
{
int value;
Node* next;
Node(
int v ) : value(v),next(0) {}
};
Node* head = 0;
void Pout( void
)
{
for( Node* p=head; p; p=p->next )
cout <<
p->value << ',';
cout << "END"<<
endl;
}
void Reverse( void )
{
// 等同于for( Node *pre=0,*next;
head&&(next=head->next,head->next=pre,next); pre=head,head=next
)
for( register Node *phead=head,*pre=0,*next; head;
)
{
next = phead->next;
phead->next =
pre;
if( !next )
{
head =
phead;
break;
}
pre =
phead;
phead = next;
}
}
int main( void
)
{
head = 0;
head = new Node(1);
head->next = new
Node(2);
head->next->next = new
Node(3);
Pout();
Reverse();
Pout();
//
内存释放与本主题无关
system("PAUSE");
return
0;
}
------------ 2006-06-21日更新 ------------
#include
using namespace std;
struct Node
{
int value;
Node* next;
Node( int v, Node* p ) : value(v), next(p) {}
};
void reverse( Node*& p )
{
Node* t = 0;
for( ; p ;
)
{
Node* _t = t;
t = p;
p =
p->next;
t->next = _t;
}
p = t;
}
ostream& operator<<( ostream& os, const Node* p )
{
os << '[';
if( p ) { os << p->value; p=p->next;
}
for( ; p; p=p->next ) os << ',' << p->value;
os << ']';
return os;
}
int main(void)
{
Node* p = new Node( 0, new Node( 1, new Node( 2,
new Node( 3, new Node( 4, new Node( 5, 0 ) ) ) ) ) );
cout << p << endl;
reverse( p );
cout <<
p << endl;
return 0;
}
输出:
[0,1,2,3,4,5]
[5,4,3,2,1,0]
网友评论2012-11-19 10:41:29
周星星
谢谢您的评论,俺本是一个谨小慎微的人,在发布这个贴子后,我就觉得文章中的“简洁”会令人误解,但修改又觉得麻烦了些,于是得过且过了一回,俺原本所说的“简洁”是希望可以去掉一些变量同时去掉一些赋值语句,因为这个代码是仓促写成了,脑中一直有个预感---有一些语句是多余的和不必要的,而不是说能将它写成一行来显摆(也许确有一点点这个意思)。
而接下来有两个不同版本的原因在于它们都有缺点,写成一行的缺点是不直观,写成数行的缺点是其中if( !next ) break硬生生打断了流程,即使到目前为止,我对这两种写法的喜好和憎恨程度都是一样的,当然这与主题无关,主题还是
a. 没有更好的算法?
b. 即使使用这种算法,可不可以减少几个变量和赋值语言?(不是行数^_^)