zoukankan      html  css  js  c++  java
  • 剑指offer 6:链表(从头到尾打印链表)

    链表的数据结构

    struct ListNode
    {
    	int value;
    	ListNode* next;
    };
    

      那么在链表的末尾添加一个节点的代码如下:

    void insert(ListNode** pHead, int value)
    {
    	ListNode* pNew = new ListNode;
    	pNew->value = value;
    	pNew->next = NULL;
    	if (*pHead == NULL)
    	{
    		*pHead = pNew;
    	}
    	else
    	{
    		ListNode* temp = *pHead;
    		while (temp->next != NULL)
    		{
    			temp = temp->next;
    		}
    		temp->next = pNew;
    	}
    }
    

      在上面的代码中,我们要特别注意函数的第一个参数是pHead是一个指向指针的指针。当我们往一个空链表中插入一个节点时,新插入的节点就是链表的头指针。由于此时会改动头指针,因此必须把pHead参数设为指向指针的指针,否则出了这个函数pHead仍然是一个空指针。

    这这里指针的指针可以这样理解——pHead是一个指向指针的指针,*pHead是一个指针,链表的结点也是指针类型,那么pHead就可以指向多个指针,这样就可以把链表的所有结点连接起来形成一条链。

      由于链表中的内存不是一次性分配的,因而我们无法保证链表的内存和数组一样时连续的。因此,如果想在链表中找到它的第i个节点,那么我们只能从头节点开始,沿着指向下一个节点的指针遍历链表,它的时间效率为O(n)。而在数组中,我们可以根据下标在O(1)时间内找到第i个元素。下面是在链表中找到第一个含有某值的节点并删除该节点的代码:

    void RemoveNode(ListNode** pHead, int value)
    {
    	if (pHead == NULL && (*pHead) == NULL)//如果链表为空
    	{
    		return;
    	}
    	ListNode* pdelete = NULL;
    	if ((*pHead)->vaule == value)
    	{
    		pdelete = *pHead;
    		*pHead = (*pHead)->next;
    	}
    	else
    	{
    		ListNode* pNode = *pHead;
    		while (pNode->next != NULL && pNode->next->value != value)
    		{
    			pNode = pNode->next;
    		}
    		if (pNode->next != NULL && pNode->next->value == value)
    		{
    			pdelete = pNode->next;
    			pNode->next = Pnode->next->next;
    		}
    	}
    	if (pdelete != NULL)
    	{
    		delete pdelete;
    		pdelete = NULL;
    	}
    }
    

     

    从尾到头打印链表

    我们可以用栈实现这种顺序。每经过一个节点的时候,把该节点放到一个栈中。当遍历完整个链表后,再从栈顶开始逐个输出节点的值,此时输出的结点的顺序已经反转过来了。这种思路的实现代码如下:

    void printf_RList(ListNode *pHead)
    {
    	stack<ListNode*>nodes;
    	ListNode* pNode = pHead;
    	while (pNode != NULL)
    	{
    		nodes.push(pNode);
    		pNode = pNode->next;
    	}
    	while (!nodes.empty())
    	{
    		pNode = node.top();
    		cout << pNode << " ";
    		nodes.pop();
    	}
    }
    

      既然想到了用栈来解决这个函数,而递归在本质上就是一个栈结构,于是很自然地又想到了用递归来实现。要实现反过来的链表,我们每访问到一个节点的时候,先递归输出它后面的节点,再输出该节点自身,这样链表的输出结果就反过来了。

    基于这样的思路不难写出如下代码:

    void printf_RList(ListNode* pHead)
    {
        if (pHead != NULL)
        {
            if (pHead->next != NULL)
            {
                printf_RList(pHead->next);
            }
            cout << pHead->value<<" ";
        }
    }
  • 相关阅读:
    nginx 平滑升级和location配置案例
    nginx
    基于zabbix的监控keepalive脑裂
    KVM部署
    基于keepalived的lvs负载均衡http集群
    高可用keepalived
    KVM
    无向图中 生成树,完全图,连通图 的区别
    java中 is
    第一章——软件工程学概述 思维导图
  • 原文地址:https://www.cnblogs.com/wuyepeng/p/9624837.html
Copyright © 2011-2022 走看看