【编程练习】链表必考重点算法

这篇博客主要讲解了链表的常见算法问题,包括单链表的反转、判断单链表是否存在环、找到环的入口、合并两个有序链表、删除重复结点以及找两个链表的第一个公共结点。此外,还提出了一道挑战性的综合题目,涉及链表拆分、反转和合并,旨在锻炼读者的链表操作能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、单链表反转

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个有序链表。
这里不细说了 上面都有提到过,读者们自行编码调试吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值