1. 简述
假设有一个没有头指针的单链表。一个指针指向此单链表中间的一个节点(不是第一个,也不是最后一个节点)。请将该节点从单链表中删除。
扩展题目:给定一个链表头指针,将单链表逆置。
2. 思路
对于第一个问题,首先把要删除的节点内容交换到后面节点上去,然后将后面的节点删除。注意,如果当前删除的节点是最后一个节点的时候,是无法搞定的。
swap(Curr->value, Curr->Link->value);
Tmp = Curr->Link;
Curr->Link = Tmp->Link;
delete Tmp;
对于第二个问题,也很简单,三个指针:Prev、Head和Next,分别指向前面的元素、当前元素和后面元素。Head是头指针,最后Head指向链表逆置后的头。注意,如果Head用函数参数传递,需要指针的指针或者指针的引用。
Node* Next;
while(Head) {
Next = Head->Link;
Head->Link = Prev;
if(Next == NULL)
Prev = Head;
Head = Next;
}
如果不加if判断,那么最后Head移动到逆置前,最后面的空指针上去了,实际上,此时Prev中正好是逆置前,最后面得一个节点。上面的那个实现,每次循环都要判断个if,这个实现只要最后一次赋值,所以这个实现更好一些。
Node* Prev = NULL;
Node* Next;
while(Head) {
Next = Head->link;
Head->link = Prev;
Prev = Head;
Head = Next;
}
Head = Prev;
}
3. 实现和测试
using namespace std;
struct Node {
int value;
Node* link;
};
void reverse(Node*& Head) {
Node* Prev = NULL;
Node* Next;
while(Head) {
Next = Head->link;
Head->link = Prev;
if(Next == NULL) // 这一步很重要,避免Head移动到空指针上面去!!
break;
Prev = Head;
Head = Next;
}
}
int main() {
Node * Head;
Head = new Node; Head->value = 0;
Head->link = new Node; Head->link->value = 1; Head->link->link = NULL;
// print head
Node * tmp = Head;
while(tmp) {
cout << tmp->value << " ";
tmp = tmp->link;
}
cout << endl;
// reverse
reverse(Head);
// print head
tmp = Head;
while(tmp) {
cout << tmp->value << " ";
tmp = tmp->link;
}
cout << endl;
// wait
system("PAUSE");
return 0;
}
4 参考
编程之美,3.4,从无头单链表表中删除节点