数据结构——单向链表和双向链表

数据结构——链表

线性表实现方法的比较:

1.顺序表的主要优点和缺点:

优点:

  1. 顺序表的实现方法简单,各种高级语言中都有数组类型,容易实现
  2. 按序号查找可通过下标直接定位,时间代价为O(1)
  3. 元素间的逻辑顺序和物理存储顺序一致,不需要借助指针,不产生结构性存储开销
  4. 顺序表是存储静态数据的理想选择
    缺点:
  5. 需要预先申请固定长度的数组
  6. 插入和删除操作需要移动大量的元素,时间代价为O(n)

2.链表的主要优点和缺点:

优点:

  1. 插入和删除操作不需要移动元素,只需修改指针的指向,时间代价为O(n),若不需要查找,则插入和删除操作的时间代价为O(1)。链表比较适合经常插入和删除元素的情况。
  2. 动态的按照需要为表中新的元素分配存储空间,无需事先了解线性表的长度。当对线性表的长度无法估计时,采用链表比较合适。
  3. 链表是存储动态变化数据的理想选择。
    缺点:
  4. 链表需要在每个结点上附件指针,用以体现元素间的逻辑关系,增加了结构性存储开销。
  5. 按序号查找元素需要遍历链表,时间代价为O(n)。

链表

  • 单向链表
  • 双向链表
  • 循环链表
  • 企业链表

单向链表

单向链表的结点分为两部分:数据域和指针域

单向链表的插入和删除,如图所示
数据结构——单向链表和双向链表_第1张图片
1.定义结点结构体

struct LinkNode
{
	int date;
	LinkNode* next;
};

2.定义链表类

class MyLinkList
{
public:
	MyLinkList();//初始化链表
	void Insert_LinkList(int pos, DataType value);//插入节点
	void RemovePos_LinkList(int pos);//删除节点
	int GetSize_LinkList();//获取链表长度
	int Find_LinkList(DataType value);//寻找数值
	void Print_LinkList();//打印
	DataType Front_LinkList();//返回头节点
	void imverse();//逆置
	void Free_LinkList();//释放链表
	~MyLinkList();

	LinkNode* head;
	int size;

};

3.链表初始化
注意:在做初始化时,给头结点申请新空间,同时将它的指针的指向设为NULL

MyLinkList::MyLinkList()
{
	head = new LinkNode;
	head->next = NULL;
	size = 0;
}

4.元素插入
本次插入使用的是头插入法
在插入元素时,对元素结点进行申请空间,指针域设为NULL,数据域赋值为value

void MyLinkList::Insert_LinkList( int pos, DataType value)
{
	if (pos<0||pos>this->size)
	{
		std::cout << "插入位置有误" << std::endl;
	}
	LinkNode* newnode=new LinkNode;
	newnode->date = value;
	newnode->next = NULL;
	LinkNode* pcurrent = this->head;
	for (int i = 0; i < pos; i++)
	{
		pcurrent = pcurrent->next;
	}
	newnode->next = pcurrent->next;
	pcurrent->next = newnode;
	this->size++;
}

5.按元素位置删除

void MyLinkList::RemovePos_LinkList(int pos)
{
	if (this->head->next==NULL)
	{
		std::cout << "链表为空,无法删除" << std::endl;
	}
	if (pos<0 || pos>this->size)
	{
		std::cout << "删除位置有误" << std::endl;
	}
	LinkNode* pcurrent = this->head;
	for (int i = 0; i < pos; i++)
	{
		pcurrent = pcurrent->next;
	}
	LinkNode* Delep= pcurrent->next;
	pcurrent->next = Delep->next;
	delete Delep;
	this->size--;
}

6.查找元素

int MyLinkList::Find_LinkList(DataType value)
{
	if (this->head->next == NULL)
	{
		std::cout << "链表为空" << std::endl;
	}
	LinkNode* pcurrent = this->head->next;
	int i=0;
	int flag = -1;
	while (pcurrent!=NULL)
	{
		if (pcurrent->date==value)
		{
			flag = i;
			break;
		}
		i++;
		pcurrent = pcurrent->next;
	}
	if (flag==-1)
	{
		std::cout << "链表内未找到" << std::endl;
	}
	return flag;
}

7.打印元素

void MyLinkList::Print_LinkList()
{
	LinkNode* pcurrent = this->head->next;
	if (pcurrent == NULL)
	{
		std::cout << "链表为空" << std::endl;
	}
	while (pcurrent!=NULL)
	{
		std::cout << (pcurrent->date) << "  ";
		pcurrent = pcurrent->next;
	}
	std::cout << std::endl;
}

8.逆置链表

void MyLinkList::imverse()
{
	LinkNode *p, *tmp;
	p = this->head->next;
	this->head->next = NULL;
	while (p)
	{
		tmp = p->next;
		p->next = this->head->next;
		this->head->next = p;
		p = tmp;
	}
}

9.释放链表

void MyLinkList::Free_LinkList()
{
	LinkNode* temp=this->head->next;
	LinkNode* Nextp;
	if (temp ==NULL)
	{
		std::cout << "链表为空" << std::endl;
	}
	while (temp !=NULL)
	{
		/*Nextp = temp;
		temp = Nextp->next;
		delete Nextp;*/
		Nextp = temp->next;
		delete temp;
		temp = Nextp;
	}
	this->head->next = NULL;
	std::cout << "链表清空" << std::endl;
	this->size = 0;
}

双向链表

在这里插入图片描述
双向链表的插入和删除,如图所示
数据结构——单向链表和双向链表_第2张图片
1.定义结点结构体

struct LinkNode
{
	LinkNode* next;
	LinkNode* prior;
	DataType date;
};

2.双向链表的类

class LinkList
{
public:
	LinkList();
	void Insert_linkList(int pos,DataType value);
	void Remove_LinkList(int pos);
	int Find_LinkList(DataType value);//寻找数值
	void Print_LinkList();//打印
	int Getsize_LinkList();
	void imverse();//逆置
	void Free_LinkList();//释放链表
	~LinkList();

	LinkNode* head;
	LinkNode* tail;
	int size;
};

3.初始化

LinkList::LinkList()
{
	this->head = new LinkNode;
	this->tail = new LinkNode;
	head->next = tail;
	tail->prior = head;
	this->size = 0;
}

4.插入

void LinkList::Insert_linkList(int pos, DataType value)
{
	if (pos < 0||pos > this->size)
	{
		cout << "位置插入有误" << endl;
	}
	LinkNode* NewNode=new LinkNode;
	NewNode->date = value;
	NewNode->next = NULL;
	NewNode->prior = NULL;

	LinkNode* pCurrent = this->head;
	for (int i = 0; i < pos; i++)
	{
		pCurrent = pCurrent->next;
	}
	LinkNode* pNext= pCurrent->next;
	NewNode->next = pNext;
	NewNode->prior = pCurrent;
	pCurrent->next = NewNode;
	pNext->prior = NewNode;
	this->size++;
}

5.删除

void LinkList::Remove_LinkList(int pos)
{
	if (pos < 0 || pos > this->size)
	{
		cout << "位置插入有误" << endl;
	}
	LinkNode* pCurrent = this->head;
	for (int i = 0; i < pos; i++)
	{
		pCurrent = pCurrent->next;
	}
	LinkNode* pDele = pCurrent->next;
	pCurrent->next = pDele->next;
	pDele->next->prior = pDele->prior;
	delete pDele;
	this->size--;
}

6.查询元素

int LinkList::Find_LinkList(DataType value)//寻找数值
{
	LinkNode* pCurrent = this->head->next;
	int idx = 0;
	int flag = -1;
	while (pCurrent != tail)
	{
		if (pCurrent->date==value)
		{
			flag = idx;
			break;
		}
		idx++;
		pCurrent = pCurrent->next;
	}
	return flag;
}

7.打印元素

void LinkList::Print_LinkList()//打印
{
	LinkNode* pCurrent = this->head->next;
	if (pCurrent ==tail)
	{
		cout << "The Linklist is empty!" << endl;
	}
	while (pCurrent != tail)
	{
		cout << pCurrent->date << "  ";
		pCurrent = pCurrent->next;
	}
	cout << endl;
}

8.逆置链表

void LinkList::imverse()//逆置
{
	LinkNode *p, *tmp;
	p = this->head->next;
	this->head->next = tail;
	tail->prior = head;
	while (p!=tail)
	{
		tmp = p->next;
		p->next = this->head->next;
		p->prior = head;
		this->head->prior = p;
		this->head->next = p;
		p = tmp;
	}
}

9.释放链表

void LinkList::Free_LinkList()//释放链表
{
	LinkNode* pCureent = this->head->next;
	LinkNode* pNext;
	while (pCureent != tail)
	{
		pNext = pCureent->next;
		delete pCureent;
		pCureent = pNext;
	}
	this->size = 0;
	cout << "The Linklist has clear!" << endl;
}

你可能感兴趣的:(数据结构,数据结构,链表)