链表(特别是单链表)的定位是链表这种数据结构的一个软肋所在,定位某一个元素你
就不得不通过遍历的方式获得。如果要寻找一个单链表的中间节点,普通的方法就是先遍历得到链表的长度,然后再通过长度遍历得到链表的中间节点。当然有一些链表通过一个特殊的头节点记录链表的长度的情况,可能要简单一些。
前一段时间,在看链表的归并排序的时候,就不得不面临着寻找链表中间节点的问题。这里给出一种实现,很可能是大家想不到的:):
1) 使用两个指针进行遍历,快指针每次步进2,慢指针每次步进1;
2) 当快指针到达链表尾部的时候,慢指针指向的就是链表的中点。
这个算法的思想和经典问题“判定链表中是否存在环”的思想是一致的,但是如果不是
有启发,真的是很难想出来:)。
实现源码为:
#include <cstdlib> #include <iostream> using namespace std; typedef struct _NODE { int value; struct _NODE *next; _NODE(int value) : value(value), next(NULL){}; }NODE, *PTRNODE; void createList(PTRNODE &head, int *val, int size) { PTRNODE curNode = NULL; for(int i=1; i<=size; i++) { if(head == NULL) { head = new NODE(val[i]); curNode = head; } else { PTRNODE newNode = new NODE(val[i]); curNode->next = newNode; curNode = curNode->next; } } } void display(PTRNODE head) { if(head == NULL) return; PTRNODE curNode = head; while(curNode != NULL) { if(curNode->next != NULL) cout << curNode->value << “->”; else cout << curNode->value; curNode = curNode->next; } cout << endl; } int getMid(PTRNODE head) { if(head == NULL) return -1; PTRNODE ptrOneStep = head; PTRNODE ptrTwoStep = head->next; while(ptrTwoStep != NULL && ptrTwoStep->next != NULL) { ptrOneStep = ptrOneStep->next; ptrTwoStep = ptrTwoStep->next->next; } return ptrOneStep->value; } int main(int argc, char *argv[]) { PTRNODE head = NULL; int count; int *val; cout << “please input node number: ” << endl; cin >> count; val = new int[count + 1]; for(int i=1; i<=count; i++) val[i] = i; createList(head, val, count); cout << “list is: ” << endl; display(head); cout << “mid val is: ” << getMid(head) << endl; delete[] val; system(“PAUSE”); return EXIT_SUCCESS; }