一、單鏈表反轉
LinkList Reserve_L(LinkList L)
{
if(L==NULL||L->next==NULL)
return 0;
LNode *p,*r;
p=L->next;//指向第一個結點
L->next=NULL;//把頭結點摘下來
while(p!=NULL)
{
r=p->next;//向後遍歷
p->next=L->next;//把p指向的結點摘下來, 第一次時next=null 充當最後一個結點
L->next=p;//頭插法,把第一個結點插在表頭之後
p=r;
}
}
上面這一種是 不算表頭的 表頭裏沒有數據
下面這一種是表頭帶數據,表頭也要丟到最後
ListNode* ReverseList(ListNode* pHead) {
if(pHead==NULL)
return NULL;
ListNode* pNode=pHead;//當前指針
ListNode* pReverseHead=NULL;//新鏈表的頭指針
ListNode* pPrev=NULL;//當前指針的前一個結點
while(pNode!=NULL){//當前結點不爲空時才執行
ListNode* pNext=pNode->next;//鏈斷開之前一定要保存斷開位置後邊的結點
if(pNext==NULL)//當pNext爲空時,說明當前結點爲尾節點
pReverseHead=pNode;
pNode->next=pPrev;//指針反轉
pPrev=pNode;
pNode=pNext;
}
return pReverseHead;
}
二、判斷單鏈表是否有環
bool isLoop(Node *head)
{
Node *fast,*slow;
slow=fast=head;
while(slow!=NULL&&fast->next!=NULL)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast)
return true;
}
return false;
}
三、判斷鏈表中的環的入口
ListNode* EnterofLoop(ListNode* pHead)
{
if(pHead==NULL||pHead->next==NULL||pHead->next->next==NULL)//結點不足三個構不成環
{
return NULL;
}
ListNode *pFast=pHead->next->next;
LiseNode *pSlow=pHead->next;
while(pFast!=pSlow)
{
if(pFast->next!=NULL&&pFast->next->next!=NULL)
{
pFast=pFast->next->next;
pSlow=pSlow->next;
}
else return NULL;
}
pFast=pHead;
while(pFast!=pSlow)
{
pFast=pFast->next;
pSlow=pSlow->next;
}
return pFast;
}
四、合併2個有序鏈表
遞歸操作:
Node mergeList(Node List1,Node List2)
{
if(List1==NULL)
return List2;
if(List2==NULL)
return List1l;
Node *resultNode;
if(list1->val<list2->val)
{
resultNode=list1;
list1=list1->next;
}
else
{
resultNode=list2;
list2=list2->next;
}
resultNode->next=mergeList(List1,List2);
return resultNode;
}
非遞歸寫法
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
ListNode *p1,*p2,*pre1,*p3;
pre1 = p1 = pHead1; p2 = pHead2;
while(p1 && p2)
{
if(p1->val > p2->val)
{
pre1->next = p2;
p3 = p2->next;
p2->next = p1;
p2 = p3;
}
pre1 = p1;
p1 = p1->next;
}
if(p2)
pre1->next = p2;
return pHead1;
}
五、刪除鏈表中重複出現的結點
(1)重複的全部刪除
pre指針指向一定不重複的結點,last是工作指針用於遍歷。
ListNode* deleteDuplication(ListNode* pHead)
{
if(pHead == NULL || pHead->next == NULL)
return pHead;
ListNode *Head = new ListNode(0);
Head->next = pHead;//在鏈表前新建一個結點,防止第一個和第二個就相同
ListNode *pre = Head;
ListNode *last = Head->next;
while(last != NULL)
{
if(last->next != NULL && last->val == last->next->val)
{
while(last->next != NULL && last->val == last->next->val)
{
last = last->next;
}
pre->next = last->next;//標誌處
last = last->next;
}
else
{
pre = pre->next;
last = last->next;
}
}
return Head->next;
}
(2)重複的結點保留一次
public static Node deleteDup3(Node x) {
Node tmp = x;
while(tmp != null) {
if (tmp.next == null) {
break;
}
if (tmp->val == tmp->next->val) {
tmp->next = tmp->next->next;
} else {
tmp = tmp->next;
}
}
return x;
}
遞歸解法
public static Node deleteDup4(Node head) {
if (head == null || head.next == null)
return head;
head.next = deleteDup4(head.next);
return head.val == head.next.val ? head.next : head;
}
六、找出兩個鏈表的第一個公共結點
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
map<ListNode*, int> m;
ListNode *p = pHead1;
while(p != NULL) {
m[p] = 1;
p = p->next;
}
p = pHead2;
while(p != NULL) {
if(m[p]) {
return p;
}
p = p->next;
}
return NULL;
}
最後一提,一個綜合的算法題目
一個鏈表假設第一個節點定位下標1,第二個爲2,下標爲奇數的結點是升序排序,偶數的結點是降序排序,如何讓整個鏈表有序?
第一步 拆分成2個鏈表保存
第二步 其中一個鏈表進行反轉
第三步 合併2個有序鏈表。
這裏不細說了 上面都有提到過,讀者們自行編碼調試吧!