<剑指offer>之链表题目

【引言】

   这几天在看<剑指offer>写的很好,跟July的各有千秋,更加注重归纳总结,笔试面试临时抱佛脚,决定要啃下这其中的46道题目。OK,把每道题目自己实现,相同的归成一类。这次把所有的与list相关的题目列出来。

【题目5】从尾到头打印list

//思路:从尾到头打印list的话,考虑用stack先把各节点保存起来,遍历完以后再将stack弹出打印即可
#include <stack>
void print_list_reverse(list_node* head)
{
	stack<char> m_list;
	if (head == NULL)
		return;
	list_node* node = head->m_pNext;
	while(node != NULL)
	{
		m_list.push(node->m_data);
		node = node->m_pNext;
	}
	while(!m_list.empty())
	{
		cout<<m_list.top()<<" ";
		m_list.pop();
	}
}
//思路:用递归模拟stack,每次遍历list当前节点的时候,递归调用下一个节点,直到list结尾
void print_list_reverse_res(list_node* head)
{
	if (head == NULL)
		return;
	list_node* node = head;
	if (node->m_pNext != NULL)
	{
		node = node->m_pNext;
		print_list_reverse_res(node);
		cout<<node->m_data<<" ";
	}
}

【题目13】在O(1)时间内删除链表节点

//void delete_node_O1(list_node* head, list_node* pto_delete)函数形式;可以看出,已经给出了要删除node的指针,我们可以很方便地找到要删除node的下一个node
//将下一个node的信息复制到当前node,再将下一个node删除,这正好相当于将当前node删除!时间复杂度是O(1),需要注意的是假设当前node是最后一个的话
//node->next为空,上面的思路就不行了,我们还是需要找到尾节点的上一个节点!如果所有链表只有一个节点,那么我们将head置空即可。so,代码如下:
void delete_node_O1(list_node* head, list_node* pto_delete)
{
	if (pto_delete == NULL || head == NULL)
		return;	
	list_node* nextNode;
	if (pto_delete->m_pNext != NULL)
	{
		nextNode = pto_delete->m_pNext;
		pto_delete->m_data = nextNode->m_data;
		pto_delete->m_pNext = nextNode->m_pNext;
		delete nextNode;
		nextNode = NULL;
		
	}
	else if (pto_delete == head)
	{	
		delete pto_delete;
		pto_delete = NULL;
		head = NULL;
	}
	else //list尾,没办法,要将前一个节点的m_pNext置为NULL只能遍历一次
	{
		list_node* node = head;
		while(node->m_pNext != pto_delete)
			node = node->m_pNext;
		nextNode = node->m_pNext;
		node->m_pNext = NULL;	
		delete nextNode;
		nextNode = NULL;
	}

}

【题目15】寻找list中倒数第k个节点

//题目给出一个list,输出该链表中倒数第k个节点。
//为符合习惯本题目,从1开始计数,即list的最后一个节点是倒数第一个
//思路:使用两个指针,刚开始同时指向list头,然后第二个指针p2前进k-1步,然后第一个指针p1和p2
//同时前进,知道p2到达list尾,这时p1指向倒数第k个节点
list_node* find_k_reverse(list_node* head, int k)
{
	if (head == NULL || k < 1)
		return NULL;
	list_node *p1, *p2;
	p1 = p2 = head;
	int i = 0;
	while(p2->m_pNext != NULL && (++i != k))
		p2 = p2->m_pNext;
	if (p2->m_pNext == NULL)//list长度小于k-1
		return NULL;
	while(p2->m_pNext != NULL)
	{
		p1 = p1->m_pNext;
		p2 = p2->m_pNext;
	}
	return p1;

}

【题目16】反转list

//给定一个list,输入参数是头结点,要求反转list,输出翻转后list的头结点
//这类问题,都不难,最好画画图啥的,需要注意的中间需要一些节点保存指针,要不会造成list的断裂,需要三个指针,当前指针,当前指针前一个指针,当前指针后一个指针
list_node* reverse_list(list_node* head)
{
	if (head == NULL)
		return NULL;
	//一共需要三个指针,当前节点之前,当前节点,当前节点之后的节点,这样才不会造成
	//调整过程中的list的断裂
	list_node* p_node = head;
	list_node* p_pre = NULL;
	list_node* p_next = p_node->m_pNext;
	while (p_next != NULL)
	{
		p_node->m_pNext = p_pre;
		p_pre = p_node;
		p_node = p_next;
		p_next = p_next->m_pNext;
	}
	if (p_next == NULL)//这个时候p_node就是原来的尾节点
	{
		p_node->m_pNext = p_pre;
	}
	return p_node;	

}

【题目17】合并两个有序list

list_node* merge_order_list(list_node* first, list_node* second)
{
	//有链表为空的情况
	if(first == NULL)
		return second;
	if(second == NULL)
		return first;
	list_node* p_result = NULL;
	if (first->m_data < second->m_data)
	{
		p_result = first;
		p_result->m_pNext = merge_order_list(first->m_pNext, second);
	}
	else
	{
		p_result = second;
		p_result->m_pNext = merge_order_list(first, second->m_pNext);
	}
	return p_result;		

}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值