剑指Offer——从尾到头打印链表

题目描述:输入一个链表的头结点,从尾到头反过来打印出每个节点的值。

分析:从尾到头打印,那就是先进后出,根据这个可以想想能不能用栈实现,这个是可以的。先按顺序把节点的值入栈,所有值入栈之后再出栈,直到栈为空。除了使用栈之外还有什么方法吗?有的,还有一个和栈类似,那就是递归,递归在本质上就是一个栈结构,所以就有两种解法。

代码如下:

声明节点对象,并提供必要的方法:

class ListNode
    {
        public object m_nValue;
        public ListNode m_pNext;
        public ListNode(object data=null)
        {
            m_nValue = data;
            m_pNext = null;
        }
        //关联两个节点
        internal static void ConnectListNodes(ListNode currentNode,ListNode nextNode)
        {
            currentNode.m_pNext = nextNode;
        }
        //删除整个链表
        internal static void DestroyListNodes(ListNode pHead)
        {
            ListNode currentNode = pHead;
            ListNode nextNode = null;
            while(currentNode!=null)
            {
                nextNode = currentNode.m_pNext;
                //执行删除(没找到对应的方法)
                currentNode = nextNode;
            }
        }
        
    }

将值存入栈的解法:

private static void PrintListReversingly_Iteratively(ListNode pHead)
        {
            Stack<object> nodes = new Stack<object>();
            ListNode pNode = pHead;
            //入栈
            while(pNode!=null)
            {
                nodes.Push(pNode.m_nValue);
                pNode = pNode.m_pNext;
            }
            //打印并出栈
            while(nodes.Count>0)
            {
                object value = nodes.Peek();
                Console.Write("{0} ", value);
                nodes.Pop();
            }
        }

递归解法:

private static void PrintListReversingly_Recursively(ListNode pHead)
        {
            ListNode pNode = pHead;
            if(pNode.m_pNext!=null)
            {
                PrintListReversingly_Recursively(pNode.m_pNext);
            }
            Console.Write("{0} ", pNode.m_nValue);
        }

测试方法:

static void Test(ListNode pHead)
        {
            PrintListReversingly_Iteratively(pHead);
            Console.WriteLine();
            PrintListReversingly_Recursively(pHead);
            Console.WriteLine();
        }

        // 1->2->3->4->5
        static void Test1()
        {
            ListNode pNode1 = new ListNode(1);
            ListNode pNode2 = new ListNode(2);
            ListNode pNode3 = new ListNode(3);
            ListNode pNode4 = new ListNode(4);
            ListNode pNode5 = new ListNode(5);

            ListNode.ConnectListNodes(pNode1, pNode2);
            ListNode.ConnectListNodes(pNode2, pNode3);
            ListNode.ConnectListNodes(pNode3, pNode4);
            ListNode.ConnectListNodes(pNode4, pNode5);

            Test(pNode1);
        }

        //只有一个节点的链表
        static void Test2()
        {
            ListNode pNode1 = new ListNode(1);

            Test(pNode1); 
        }

        //空链表
        static void Test3()
        {
            ListNode pNode1 = new ListNode();

            Test(pNode1);
        }

Main方法:

static void Main(string[] args)
        {
            Test1();
            Test2();
            Test3();
            Console.ReadKey();
        }
总结:要点就是要想到栈,使用递归方法要小心,当链表非常长的时候,就会导致函数调用的层级很深,从而有可能导致函数调用栈溢出。

猜你喜欢

转载自blog.csdn.net/a_clear_chen/article/details/80240260
今日推荐