【編程練習】鏈表必考重點算法

一、單鏈表反轉

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個有序鏈表。
這裏不細說了 上面都有提到過,讀者們自行編碼調試吧!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章