菜鸟玩算法·数据结构与算法·第2期·链表操作-单向链表

链表操作

    我们在讲C++的时候,详细讲解过数组。并指出数组的大小是提前声明好以及在内存中存储是连续的地址,正式因为是连续地址,这就导致了一些问题。例如,我们如果要在数组中间添加一些数据,则需要后面所有的数据都要随着移动。这就给数据处理带来了很多不便,因此针对这个问题,数据结构中提供了链表操作

    链表操作主要包括六种:单向链表、双向链表、循环链表、跳跃链表、自组织链表、稀疏链表。下面说一下链表当中的基本单元,链表当中主要包括内容信息指向链表指针。我们从下面图来详细讲解:

                                                                    

     从上图我们可以看出,指针P指向链表中10所在节点1的内存地址;节点1中的指针指向节点2(数据8)所在地址;节点2中的指针指向节点3(数据50)所在地址,节点3中的指针指向空地址。

单向链表

    单向链表,我们从名字上就应该意识到,这个其实就是一直向同一方向指向的链表。下面我们通过程序来查看:

#include <iostream>

using namespace std;

//单向链表类
class ListClass
{
public:
	ListClass();
	~ListClass();
	ListClass(int iTmpVar, ListClass *iTmpList);


	int info;
	ListClass *next;

private:

};

ListClass::ListClass()
{
	next = 0;
}

ListClass::ListClass(int iTmpVar, ListClass *iTmpList = NULL)
{
	info = iTmpVar;
	next = iTmpList;
}

ListClass::~ListClass(){}

int main()
{
	ListClass *listVar = new ListClass(10, NULL); 
	listVar->next = new ListClass(11, NULL);
	listVar->next->next = new ListClass(12, NULL);

	//访问每个链表的信息,并进行打印
	cout << listVar->info << "  " << listVar->next->info  << "  "<< listVar->next->next->info<< endl;

	getchar();
}

运行结果

10  11  12

我们可以看到,单向链表如果只保留head头指针,要访问最后的数据则需要依次访问中间所有的指针,直到指向最后的数据才可以。因此,我们需要引入指向末尾的指针tail。下面我们来看一下添加了head和tail指针后的实例:


#include <iostream>
#include <list>

using namespace std;

//单向链表节点类
class ListNodeClass
{
public:
	ListNodeClass();
	~ListNodeClass();
	ListNodeClass(int iTmpVar, ListNodeClass *iTmpList);


	int info;
	ListNodeClass *next;

private:

};

//单向链表类
ListNodeClass::ListNodeClass()
{
	next = 0;
}

ListNodeClass::ListNodeClass(int iTmpVar, ListNodeClass *iTmpList = NULL)
{
	info = iTmpVar;
	next = iTmpList;
}

ListNodeClass::~ListNodeClass() {}


class InitListClass
{
public:
	InitListClass();
	~InitListClass();
	void addToHead(int iTmp);
	void addToTail(int iTmp);
	int deleteFromHead();
	int deleteFromTail();
	void deleteNode(int iTmp);
	bool isInList(int iTmp) const;
private:
	ListNodeClass *head, *tail;
};

/*初始头和尾指针为空指针*/
InitListClass::InitListClass()
{
	head = tail = NULL;
}

/*添加头信息*/
void InitListClass::addToHead(int iTmp)
{
	head = new ListNodeClass(iTmp, head);
	if (tail == NULL)
		tail = head;    //头和尾指向同一地址
}

/*添加尾信息*/
void InitListClass::addToTail(int iTmp)
{
	if (tail != NULL)
	{
		tail->next = new ListNodeClass(iTmp); //添加下一节点
		tail = tail->next;
	}
	else
		head = tail = new ListNodeClass(iTmp);
}

/*从头删除信息*/
int InitListClass::deleteFromHead()
{
	int iReturnInfo = head->info;
	ListNodeClass *tmpClass = head;
	if (head == tail)
		head = tail = NULL;
	else
		head = head->next;
	delete tmpClass;
	return iReturnInfo;
}


/*从尾删除信息*/
int InitListClass::deleteFromTail()
{
	int iReturnInfo = tail->info;
	if (head == tail) //链表中只有一个节点
	{
		delete head;
		head = tail = NULL;
	}
	else
	{
		ListNodeClass *tmpClass;
		for (tmpClass = head; tmpClass->next != tail; tmpClass = tmpClass->next) //循环指向尾节点上一节点
			delete tail;
		tail = tmpClass;
		tail->next = NULL;
	}
	return iReturnInfo;
}


/*删除节点*/
void InitListClass::deleteNode(int iTmp)
{
	if (head != NULL)
	{
		if (head == tail && iTmp == head->info)   //链表只有一个数据
		{
			delete head;
			head = tail = NULL;
		}
		else if (iTmp == head->info)    //链表超过一个数据,其中删除的节点为数据头  
		{
			ListNodeClass *tmpClass = head;
			head = head->next;
			delete tmpClass;
		}
		else
		{
			ListNodeClass *predClass, *tmpClass;
			for (predClass = head, tmpClass = head->next; tmpClass != NULL && !(tmpClass->info == iTmp); predClass = predClass->next, tmpClass = tmpClass->next);
			if (tmpClass != NULL)
			{
				predClass->next = tmpClass->next;
				if (tmpClass == tail)
					tail = predClass;
				delete tmpClass;
			}
		}
	}
}
/*判断链表中是否存在指定数据*/
bool InitListClass::isInList(int iTmp) const
{
	ListNodeClass *tmpClass;
	for (tmpClass = head; tmpClass != NULL && !(tmpClass->info == iTmp); tmpClass = tmpClass->next);  //遍历链表中数据,并进行一一对比
	return tmpClass != NULL;
}
InitListClass::~InitListClass() {}

int main()
{
	InitListClass *listVar = new InitListClass(); //创建链表
	listVar->addToHead(10);
	listVar->addToTail(9);  //在尾部添加数据
	listVar->addToTail(8);

	//cout << listVar->deleteFromHead() << endl;   //从头开始删除数据
	//cout << listVar->deleteFromHead() << endl;
	//cout << listVar->deleteFromHead() << endl;
	listVar->deleteNode(8);                       //删除节点内的8信息
	cout << listVar->isInList(8) << endl;         //判断数据是否存在
	getchar();
}

运行结果

0

下面我们来聊一聊链表中的插入、删除、查找操作:

更多《计算机视觉与图形学》知识,可关注下方公众号:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值