1 template<class T> 2 void swap(myList<T> list, ListNode<T>* node1, ListNode<T>* node2) 3 { 4 if(node1 == node2) 5 return; 6 if(node1->next == node2) 7 { 8 ListNode<T>* prev = list.FindPrev(node1); 9 node1->next = node2->next; 10 node2->next = node1; 11 prev->next = node2; 12 } 13 else if(node2->next == node1) 14 { 15 ListNode<T>* prev = list.FindPrev(node2); 16 node2->next = node1->next; 17 node1->next = node2; 18 prev->next = node1; 19 } 20 else 21 { 22 ListNode<T>* prev1 = list.FindPrev(node1); 23 ListNode<T>* prev2 = list.FindPrev(node2); 24 ListNode<T>* temp = node1->next; 25 node1->next = node2->next; 26 node2->next = temp; 27 prev1->next = node2; 28 prev2->next = node1; 29 } 30 }
(1)找出单链表倒数第k个元素
笨方法:先遍历整个单链表获得链表的长度n,然后再遍历第二次获得链表的第n-(k-1)个元素即得到单链表的倒数第k个元素,这样一来就需要遍历两次链表。
改进的方法:遍历一次单链表,单在一次遍历中使用两个指针,其差距为k,这样一来当第一个指针达到最后一个元素时,第二个指针就刚好指向倒数第k个元素,具体的实现如下:
1 template<class T> 2 ListNode<T>* FindKthNode(myList<T> list, int k) 3 { 4 ListNode<T>* ptr1 = list.head; 5 ListNode<T>* ptr2 = list.head; 6 7 for(int i = 0; i < k; i++) 8 { 9 ptr1 = ptr1->next; 10 if(ptr1 == NULL) 11 return NULL; 12 } 13 14 while(ptr1 != NULL) 15 { 16 ptr1 = ptr1->next; 17 ptr2 = ptr2->next; 18 } 19 return ptr2; 20 }
(2)单链表反转
单链表反转就是将每一个结点中指向下一个元素的指针改为指向下一个元素,最后头结点指向原链表中最后一个结点。
1 template<class T> 2 void ReverseList(myList<T> list) 3 { 4 if(list.isEmpty()) 5 return; 6 7 //只有一个结点时不需要反转 8 if(list.head->next->next != NULL) 9 { 10 ListNode<T>* prev = list.head->next; 11 ListNode<T>* curr = prev->next; 12 ListNode<T>* pnext = NULL; 13 prev->next = NULL; 14 15 while(curr->next != NULL) 16 { 17 pnext = curr->next; 18 curr->next = prev; 19 20 prev = curr; 21 curr = pnext; 22 } 23 curr->next = prev; 24 list.head->next = curr; 25 } 26 }
还可以减少局部变量,用更简单的方法实现:
1 void reverse(test* head) 2 { 3 test* pe = head; 4 test* ps = head->next; 5 while(ps) 6 { 7 pe->next = ps->next; 8 ps->next = head; 9 head = ps; 10 ps = pe->next; 11 } 12 }
(3)从头到尾输出单链表
对此问题,有两种比较直接的方法:反转单链表和压栈。反转单链表使得原来的单链表发生了改变,操作比较多;压栈需要额外的维护栈操作。一个至少在代码量少比较简洁的方法是利用递归:
1 template<class T> 2 void ReversePrintRecu(ListNode<T>* node) 3 { 4 if(node->next != NULL) 5 { 6 ReversePrintRecu(node->next); 7 } 8 cout<<node->data<<endl; 9 } 10 11 template<class T> 12 void ReversePrint(myList<T> list) 13 { 14 if(!list.isEmpty()) 15 { 16 ListNode<T>* node = list.head->next; 17 ReversePrintRecu(node); 18 } 19 }
引申:如果要求定义一个函数不适用任何变量求一个字符串的长度,那么也可以使用递归的方式实现:
1 int RecuStrLength(char* str) 2 { 3 return ((*str) != '