主题:逆置链表算法请教(请尽可能使算法高效率)
雨523
[专家分:200] 发布于 2006-12-17 13:25:00
写一个算法,对一带头结点且仅设队尾指针的链式循环队列就地逆置.
(即队头变队尾,队尾变队头)
链队头的结点结构定义如下:
typedef struct Qnode{
Qelemtype data;
struct Qnode,*next;
}Qnode,*LinkQueue;
回复列表 (共6个回复)
沙发
雪光风剑 [专家分:27190] 发布于 2006-12-17 13:49:00
建立一个新队列
原队从队尾开始出列
取出的元素放入新队列
最后原队列为空后返回新队列
板凳
雨523 [专家分:200] 发布于 2006-12-17 14:58:00
楼上的做法错误
3 楼
leolhc [专家分:430] 发布于 2006-12-17 21:59:00
p=L->next;L->next=NULL;
while(p)
{
s=p;
p=p->next;
s->next=L->next;
L->next=s;
}
4 楼
雪光风剑 [专家分:27190] 发布于 2006-12-17 22:21:00
[quote]楼上的做法错误[/quote]
我想问的是哪错了?
所有的逆置最基本的想法就是改变指针的顺序
我把所有的元素取出来按照逆序重排这种方法你可以说效率有限,但是绝对不是错的!
5 楼
雪光风剑 [专家分:27190] 发布于 2006-12-17 22:36:00
给你找到了下述资料:
问题描述:给定一个单向链表,如何进行倒置
思路1:从表头走下去,逐个next指针向回指,中间要注意不能把下一个节点丢掉。
所以循环里面应该随时保证有三个节点的存在.
思路2:使用栈将节点完全存入,然后逐个弹出,在弹出的过程中对next指针赋值。
这里程序写了两种解决方案a.自定义栈类 b.使用STL的栈
思路3: 使用递归程序解决。节点数为N的倒叙策略实际上相当于去掉头节点后的N-1的倒序再把头补在尾部。
程序如下:
// ReverseLinkList.cpp
//
#include "stdafx.h"
#include<iostream>
#include<stack>
using namespace std;
class LinkNode
{
public:
int number;
LinkNode * next;
};
class StackNode
{
public:
LinkNode * data ;
StackNode * next;
};
class Stack
{
//自定义的栈类
public:
StackNode * top ;
int size ;
public:
Stack()
{
top = NULL;
size = 0 ;
}
void push(LinkNode * node)
{
if(size ==0 )
{
top = new StackNode;
top->data = node;
top->next = NULL;
}
else
{
StackNode * temp = new StackNode;
temp->data = node;
temp->next = top;
top = temp;
}
size ++;
}
LinkNode* pop()
{
StackNode * temp = top;
LinkNode* returnData = NULL;
top = top->next;
size --;
returnData=temp->data;
delete temp;
return returnData;
}
};
LinkNode * createLinkList()
{
//建立链表的过程,用于测试
LinkNode * head = new LinkNode;
LinkNode * last = head;
head->number = 0 ;
for( int i = 1 ; i<=4 ; i++)
{
LinkNode * temp = new LinkNode;
temp->number = i ;
temp->next = NULL;
last->next = temp;
last = temp;
}
return head;
}
LinkNode * reverseLinkList1(LinkNode * head)
{
//倒序链表,递归方案
LinkNode * myHead = head;
LinkNode * returnHead =NULL;
LinkNode * t1 = myHead->next;
if(t1->next != NULL)
{
returnHead = reverseLinkList1(t1);
t1->next = myHead;
myHead->next = NULL;
}
else
{
t1->next = myHead;
return t1;
}
return returnHead;
}
LinkNode * reverseLinkList(LinkNode * head)
{
//倒序链表 , 思路一,直接循环
LinkNode * t1 = head;
LinkNode * t2 = head->next;
LinkNode * t3 = t2->next;;
head ->next = NULL;
while (t3!=NULL)
{
t2->next = t1;
t1= t2;
t2 = t3;
t3 = t3->next;
}
t2->next = t1;
return t2;
}
void countList(LinkNode * head)
{
//遍历链表,用于测试
LinkNode * temp = head;
while (temp!=NULL)
{
cout<<temp->number<<"------>";
temp = temp->next;
}
cout<<endl;
}
LinkNode * reverseLinkList2(LinkNode * head)
{
//倒序链表,自定义栈的解决方案
Stack a ;
LinkNode * temp = head;
while(temp!=NULL)
{
a.push(temp);
temp=temp->next;
}
LinkNode * returnHead = temp = a.pop();
while(a.size>0)
{
temp->next = a.pop();
temp = temp->next;
}
temp->next = NULL;
return returnHead;
}
LinkNode * reverseLinkList3(LinkNode * head)
{
//倒序链表,系统栈的解决方案
std::stack<LinkNode*> s;
LinkNode * temp = head;
while(temp!=NULL)
{
//a.push(temp);
s.push(temp);
temp=temp->next;
}
LinkNode * returnHead = temp = s.top();
s.pop();
while(!s.empty())
{
temp->next = s.top();
s.pop();
temp = temp->next;
}
temp->next = NULL;
return returnHead;
}
int _tmain(int argc, _TCHAR* argv[])
{
//测试用主函数
LinkNode * head = NULL;
LinkNode * newhead = NULL;
head = createLinkList();
countList(head);
newhead = reverseLinkList3(head);
cout<<"****************hahaha*****************"<<endl;
countList(newhead);
return 0;
}
////我的方法是第二种思路
6 楼
forjane [专家分:5670] 发布于 2006-12-18 02:02:00
遍历链表,顺序取出节点,插入新表的表头位置
应该是最直接有效的方法了
void reverve(LinkQueue *L)
{
LinkQueue p,q,tmp=NULL;
if(*L==NULL) return;
for(q=*L,p=q->next;p!=NULL;q=p,p=p->next)
{
q->next=tmp;
tmp=q;
}
*L=q;
}
有没有头节点都不影响算法,没头节点你就调用
reverse(&L);
有头节点你就调用
reverse(&(L->next));
我来回复