【单链表】【单链表类的设计】【move函数找到第i个结点】【struct结点类】【设置表长currentLength代替每次遍历】

目录

【单链表的概念】

【单链表类的设计】

 【几点注意】

【各个功能函数的具体实现】


 【单链表的概念】

        相比于顺序表,每个结点增加了一个指针字段,如“next,该指针指向它的直接后继结点最后一个结点的next字段为空。一个数据结点由两个部分组成,一个是存储数据元素本身,另外一个存储它的直接后继元素的存储地址。我们对单链表附加了一个头结点,为了在单链表里面插入和删除操作更加方便

【单链表类的设计】

template <class elemType>
class sLinkList :public list<elemType>
{
private:
	struct node//把结点类定义成struct类而不是class类
	{
		elemType data;//保存数据元素的部分
		node* next;//指向下一个数据元素的指针
		node(const elemType& x, node* n = NULL) { data = x; next = n; }
		node():next(NULL){}
		~node() {};
	};
	node* head;//指向头结点的一个指针
	int currentLength;//数据的长度
	node* move(int i)const;//保存了第i个结点的存储地址
public:
	sLinkList()
	{
		head = new node;
		currentLength = 0;
	}//这个构造函数中没有把头结点的next指向null,是因为node类里面的缺省构造函数把next指向了null
	~sLinkList() { clear(); delete head; }//析构函数
	void clear();//清空单链表
	int length()const { return currentLength; }//返回表长
	void insert(int i, const elemType& x);//插入
	void remove(int i);//删除
	int search(const elemType& x)const;//查找
	elemType visit(int i)const;//定位访问
	void traverse()const;//遍历
};

 【几点注意】

(1)代码段的第5行:

        把结点类定义成struct类而不是class类,struct类默认访问权限都是公有的,方便单链表进行操作。这样的定义是安全的,因为struct类被我们定义到了单链表类的私有成员部分,用户仍然访问不到。

struct node

(2) struct结点类有两个构造函数:

node(const elemType& x, node* n = NULL) { data = x; next = n; }//初始化数据成员部分和next结点
node():next(NULL){}//将next结点置为NULL

3)设置了一个表长currentLength:

        当我们想要求表长的时候,需要从头到尾遍历一遍单链表,才能返回这个表的表长,这个操作的时间性能是很差的,那应该怎么解决呢?

        我们想到一个方法,就是用空间换时间,所以我们增加了一个数据成员,来保存当前单链表的长度,随时对这个数据成员进行维护。

int currentLength;

(4)设计了一个工具函数move( int  i ):

        保存了第 i 个结点的存储地址,链表的插入、删除操作都需要将指针移到被操作结点的前一结点,通过函数move实现。(后面将会介绍move函数的具体实现过程)

node* move(int i)const;

【各个功能函数的具体实现】

//move函数
template<class elemType>
sLinkList<elemType>::node* sLinkList<elemType>::move(int i) const
{
	node* p = head;
	while (i-- >= 0)
		p = p->next;
	return p;
}
//清空
//单链表中所有的指针都是动态申请的,如果只是把head的next置为null是不负责任的,那么后面所有的结点都丢失了,会造成内存泄漏
template <class elemType>
void sLinkList<elemType>::clear()
{
	node* p = head->next, * q;
	head->next = NULL;
	while (p != NULL)
	{
		q = p->next;//用q记录p后面结点的地址,以防在删除p之后,找不到p后面的结点,造成内存泄漏
		delete p;
		p = q;
	}
	currentLength = 0;
}
//insert函数
template<class elemType>
void sLinkList<elemType>::insert(int i, const elemType& x)
{
	node* pos;
	pos = move(i - 1);//找到i-1的地址
	pos->next = new node(x, pos->next);//调用了node类的构造函数
	++currentLength;
}
//remove函数
template<class elemType>
void sLinkList<elemType>::remove(int i)
{
	node* pos, * delp;
	pos = move(i-1);
	delp = pos->next;
	pos->next = delp->next;
	delete delp;
	--currentLength;
}
//visit函数
template<class elemType>
elemType sLinkList<elemType>::visit(int i) const
{
	return move(i)->data;
}
//traverse函数
template<class elemType>
void sLinkList<elemType>::traverse() const
{
	node* p = head->next;
	cout << endl;
	while (p != NULL)
	{
		cout << p->data << ' ';
		p = p->next;
	}
	cout << endl;
}
//search()函数
template<class elemType>
int sLinkList<elemType>::search(const elemType& x) const
{
	node* p = head - < next;
	int i = 0;
	while (p != NULL && p->data != x)
	{
		p = p->next;
		i++;
	}
	if (p == NULL)
		return -1;
	else
		return i;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值