这道题目有两种算法,既然是要反转,那么肯定是要破坏原有的数据结构的: 算法:我们需要额外的两个变量来存储当前节点curr的下一个节点next、再下一个节点nextnext:public static Link ReverseLink1(Link head)
{
Link curr = head.Next;
Link next = null;
Link nextnext = null; //if no elements or only one element exists
if (curr == null || curr.Next == null)
{
return head;
} //if more than one element
while (curr.Next != null)
{
next = curr.Next; //1
nextnext = next.Next; //2
next.Next = head.Next; //3
head.Next = next; //4
curr.Next = nextnext; //5
}
return head;
}
算法的核心是while循环中的5句话 我们发现,curr始终指向第1个元素。 此外,出于编程的严谨性,还要考虑2种极特殊的情况:没有元素的单链表,以及只有一个元素的单链表,都是不需要反转的。
C语言实现
非递归方式:这是一般的方法,总之就是用了几个临时变量,然后遍历整个链表,将当前节点的下一节点置为前节点
void reverse(node*& head) { if ( (head == 0) || (head->next == 0) ) return;// 边界检测 node* pNext = 0; node* pPrev = head;// 保存链表头节点 node* pCur = head->next;// 获取当前节点 while (pCur != 0) { pNext = pCur->next;// 将下一个节点保存下来 pCur->next = pPrev;// 将当前节点的下一节点置为前节点 pPrev = pCur;// 将当前节点保存为前一节点 pCur = pNext;// 将当前节点置为下一节点 } head->next = 0; //将旧head节点设置为尾部节点 head = pPre; //设置当前遍历的最后一个节点为新的头节点 }
递归方式:这个方法是采用了递归算法,也就是在反转当前节点之前先反转其后继节点,利用函数的调用堆栈构建了一个临时链表。采用此算法需要注意的是,头结点必须要传入的是引用,因为在递归跳出的时候要切断链表,否则链表将会形成一个回环。
node* reverse( node* pNode, node*& head) { if ( (pNode == 0) || (pNode->next == 0) ) // 递归跳出条件 { head = pNode; // 将链表切断,否则会形成回环 return pNode; } node* temp = reserve(pNode->next, head);// 递归 temp->next = pNode;// 将下一节点置为当前节点,既前置节点 return pNode;// 返回当前节点 }