《剑指offer》【面试题5:从尾到头打印链表】

面试题五:从尾到头打印链表


链表是一种频繁被提及的数据结构,它是通过指针把若干个结点连接成链状的一种数据结构。由于链表的操作是通过指针来实现的,所以在这里指针的正常使用也是面试官所容易提及的一个考点。


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

分析:当遇见这种题的时候,瞬间感觉自己对于链表的所有认识全部给抛了出来,什么双向链表,循环链表了等等,但是额外的想这些只会为你的大脑提供更多的负担,解决确实可以解决,但是这样会使链表的结构发现相应的改变。或许有的会想到单链表不是只能从前向后遍历,倒着从后往前遍历不是不可以吗,面试题就是抓住了这点,所以需要你灵活的去巧妙的进行解决这个问题。这里我们是利用了另一种数据结构---栈的特性---先进后出,我们通过先进后出这个特点,把链表中的所有数据结点从前向后遍历,并依次的压入栈中,当遍历完整个链表以后,再从栈顶开始逐个的弹出(出栈),这样我们就实现了链表的从尾到头打印链表了。
图解:



相应的栈和链表类的部分功能的实现 

#include <iostream>
#include <assert.h>
using namespace std;

//栈
class CDstack
{
public:
	CDstack()
	{
		//cout<<"CDstack()"<<endl;
		_elem = new int[INITSIZE];
		_top = 0;
		_topsize = INITSIZE;
	}
	~CDstack()
	{
		delete[]_elem;
	}
	bool isfull()//判满
	{
		return _top == _topsize;
	}
	bool isempty()//判空
	{
		return _top == 0;
	}
	void resize()//扩容
	{
		int *newelem = new int[_topsize*2];
		for (int i = 0; i<_top; i++)
		{
			newelem[i] = _elem[i];
		}
		delete []_elem;
		_elem = newelem;
		_topsize = _topsize*2;
	}
	void push(int val)
	{
		if (isfull())
		{
			resize();
		}
		_elem[_top++] = val;
	}
	void pop(int *rtval)//获取值且删除
	{
		if (!isempty())
		{
			*rtval = _elem[--_top];
		}
	}
	void show()
	{
		for (int i = 0; i<_top;i++)
		{
			cout<<_elem[i]<<"   ";
		}
		cout<<endl;
	}
	int max_size()
	{
		return _topsize;
	}
	int data_size()
	{
		return _top;
	}
private:
	enum{INITSIZE = 20};//初始格子大小
	int *_elem;
	int _top;//栈顶指针,标记当前可以存放数据的下标
	int _topsize;//总格子数
};

//结点
class Node
{
public:
	Node()
	{
		pnext = NULL;
	}

private:
	int data;
	Node *pnext;
	friend class CList;
};

//链表
class CList
{
public:
	CList()
	{
		phead = new Node();
		//cout<<"CList()"<<endl;
	}

	~CList()
	{
		Node* p = phead;
		while(phead->pnext != NULL)
		{
			p = phead->pnext;
			phead->pnext = p->pnext;
			delete p;
		}
		delete phead;
	}

	void insert(int val)
	{
		Node *p = new Node();
		p->data = val;
		p->pnext = phead->pnext;
		phead->pnext = p;
	}
	//获取头结点后面的结点的值,并删除这个结点
	void gethead_data(int *val)
	{
		Node *p = phead->pnext;
		*val = p->data;
		phead->pnext = p->pnext;
		delete p;
	}
	bool isempty()
	{
		return phead->pnext == NULL;
	}
	void show()
	{
		Node *p = phead->pnext;
		while(p != NULL)
		{
			cout<<p->data<<"   ";
			p = p->pnext;
		}
		cout<<endl;
	}

private:
	Node* phead;
};

面试题五代码详解:

//面试题五:
void last_front_ShowList(CList *phead)
{
	assert(phead != NULL);
	CDstack stack1;
	while(!phead->isempty())
	{
		int val;
		phead->gethead_data(&val);
		stack1.push(val);
	}

	while(!stack1.isempty())
	{
		int retval;
		stack1.pop(&retval);
		cout<<retval<<"   ";
	}
	cout<<endl;
}
int main()
{
//-------------------------------面试题五测试用例:------------------------------------
	
	//测试链表有多个结点的链表
	CList list1;
	for (int i = 10; i>0; i--)
	{
		list1.insert(i);
	}
	//list1.show();
	cout<<"链表有多个结点的链表"<<endl;
	last_front_ShowList(&list1);

	//测试链表有一个结点的链表
	CList list2;
	list2.insert(15);
	cout<<"链表有一个结点的链表"<<endl;
	last_front_ShowList(&list2);

	//测试链表头结点指针为NULL
	CList list3;
	cout<<"链表头结点指针为NULL"<<endl;
	last_front_ShowList(&list3);
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值