链表相关笔试题(一)

1.从尾到头打印单链表

方法一:可以用栈实现,遍历链表,每经过一个结点,把该结点放入栈中,当遍历完整个链表后,从栈顶开始逐个输出结点的值,此时输出的结点的顺序就反转过来了

实现代码:

void PrintTailToHead(ListNode *pHead)
{
    stack<ListNode*> nodes;
    ListNode* node = pHead;
    while(node != NULL)
    {
        nodes.push(node);
        node = node->next;
    }
    while(!nodes.empty())
    {
        node = nodes.top();
        printf("%d    ", node->data);
        nodes.pop();
    }
}

方法二:用递归实现,每访问到一个结点时,先递归输出它后面的结点,再输出该结点

实现代码:

void PrintTailToHead(ListNode *pHead)
{
	if(pHead != NULL)
	{
		if(pHead->next != NULL)
		{
			PrintTailToHead(pHead->next);
		}
		printf("   %d",pHead->data);
	}
}

2.在O(1)时间删除链表结点

分析:从头遍历链表得到要被删除结点的下一个结点,然后把下一个结点的内容复制到需要删除的结点上,最后把下一个结点删除

实现代码:

void Delete(ListNode*& pHead, ListNode* pDelNode)
{
	if (pHead == NULL || pDelNode == NULL)
	{
		return;
	}

	if (pDelNode->next != NULL)
	{
		ListNode* pNext = pDelNode->next;
		pDelNode->data = pNext->data;
		pDelNode->next = pNext->next;
		delete pNext;
		pNext = NULL;
	}
	else if (pHead == pDelNode)
	{
		delete pDelNode;
		pDelNode = NULL;
		pHead = NULL;
	}
	else
	{
		ListNode* cur = pHead;
		while (cur->next != pDelNode)
		{
			cur = cur->next;
		}

		cur->next = NULL;
		delete pDelNode;
		pDelNode = NULL;
	}
}


3.链表中倒数第K个结点

方法一:遍历链表两次,第一次统计出链表中结点的个数,第二次就能找到倒数第K个结点

方法二:定义两个指针,第一个指针从链表的头开始遍历向前走K-1,第二个指针保持不动,从第K步开始,第二个指针也开始从链表的头开始遍历,当第一个指针到达链表的尾时,第二个指针正好是倒数第K个结点

实现代码:

ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(pListHead == NULL || k == 0){
            return NULL;
        }
        ListNode *fast = pListHead;
        ListNode *slow = pListHead;
        k = k-1;
        while(k--){
            if(fast->next != NULL){
                fast = fast->next;
            }
            else{
                return NULL;
            }
        }
        while(fast->next){
            fast = fast->next;
            slow = slow->next;
        }
        return slow;
    }


4.反转链表

实现代码:

ListNode* ReverseList(ListNode* pHead) {
        ListNode *cur = pHead;
        ListNode *newhead = NULL;
        while(cur != NULL){
            ListNode *tmp = cur;
            cur = cur->next;
            tmp->next = newhead;
            newhead = tmp;
        }
        return newhead;
    }


5.合并两个排序的链表

实现代码:

    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        if(pHead1 == NULL){
            return pHead2;
        }
        else if(pHead2 == NULL){
            return pHead1;
        }
        ListNode* newHead = NULL;
        if(pHead1->val < pHead2->val){
            newHead = pHead1;
            pHead1 = pHead1->next;
        }
        else{
            newHead = pHead2;
            pHead2 = pHead2->next;
        }
        ListNode* cur = newHead;
        while(pHead1 && pHead2){
            if(pHead1->val < pHead2->val){
                cur->next = pHead1;
                cur = cur->next;
                pHead1 = pHead1->next;
            }
            else{
                cur->next = pHead2;
                cur = cur->next;
                pHead2 = pHead2->next;
            }
        }
        if(pHead1 != NULL){
            cur->next = pHead1;
        }
        else if(pHead2 != NULL){
            cur->next = pHead2;
        }
        return newHead;
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值