数据结构之链表

本文详细介绍了链表的概念,包括单链表和双链表的数据结构及操作。针对两种链表,分别展示了如何建立、合并、插入元素、排序和删除节点的C++代码实现。内容涵盖头插、尾插、指定位插入、链表排序和结点删除等核心操作。
摘要由CSDN通过智能技术生成

链表

说明:链表也是一种线性表,但与顺序表不同,它在内存中并不是连续一段连续的内存,而是将存储单元分布在内存的任意地址上,由每个结点中的指针域连接起来

1.单链表

  • 建立链表
  • 链表合并
  • 链表插入(头插、尾插、指定位插入)
  • 链表排序
  • 链表结点删除

2.双链表

  • 建立
  • 合并
  • 插入(头插、尾插、指定位插入)
  • 排序
  • 链表结点删除

单链表代码

#include<iostream>

using namespace std;

typedef int Elemtype;
//定义链表结构

typedef struct node
{
	Elemtype data;			//数据域
	struct node* next;		//指针域
}LNode,* LinkList;

//函数区域
//生成大小为size的链表,并在生成过程中赋值
LinkList CreatLinkList(int size);
//头插入
void HeadInsert(LinkList& headnode, Elemtype data);
//尾插入
void TailInsert(LinkList& node, Elemtype data);
//指定位置插入
void InserLink(LinkList& headnode, Elemtype data, int n);
//销毁链表
void DirstLink(LinkList& HeadNode);

//int main()
//{
//	LinkList p = CreatLinkList(5),k;
//	k = p;
//	InserLink(k, 3, 3);
//	InserLink(k, 5, 5);
//	InserLink(k, 6, 6);
//	while (k != NULL)
//	{
//		cout << k->data << " ";
//		k = k->next;
//	}
//
//	return 0;
//}
// 生成大小为size的链表并返回链表首地址
LinkList CreatLinkList(int size)
{
	LinkList p, q, list = NULL;
	p = q = NULL;
	Elemtype data;
	for (int i = 0; i < size; i++)
	{
		cin >> data;
		p = new LNode;
		p->data = data;
		p->next = NULL;
		if (list == NULL)		//第一次赋值时将首地址赋给list
		{
			list = p;
		}
		else					//之后的赋值都是通过q来向后增加空间
		{
			q->next = p;
		}
		q = p;
	}
	return list;				//将首地址返回

}
//	链表头插入
void HeadInsert(LinkList& headnode, Elemtype data)
{
	LinkList p = new LNode;
	p->data = data;
	p->next = NULL;
	p->next = headnode;			//先将新的空间连在headnode结点的前面
	headnode = p;				//然后把headnode的指向转为p
}

//链表尾插入

void TailInsert(LinkList& node, Elemtype data)
{
	LinkList p = new LNode;
	p->data = data;
	p->next = NULL;
	if (node == NULL)		//判断链表是否为空链表
		node = p;
	else
	{
		LinkList q = node;	//非空链表则找到最后一个空间
		while (q->next != NULL)		//最后一个空间的特征是它的指针域为空
		{
			q = q->next;
		}
		q->next = p;		//将最后一个空间与要插入的空间连起来
	}
	
}
//将数据插入到第n位
void InserLink(LinkList& headnode, Elemtype data, int n)
{
	if (n <= 0)									//判断插入的位置是否合法
	{
		cout << "插入位置非法!" << endl;
		exit(0);
	}
	int i = 1;
	LinkList p = headnode, r = NULL;			//定义p来指向头结点
	while (i != n)								//通过循环找到第n个位置的结点
	{
		r = p;									//r是p前一个结点
		p = p->next;
		i++;
	}
	if (p == headnode)							//如果恰好插入到第一个
	{
		HeadInsert(headnode, data);
	}
	else
	{											//不是插入到第一个
		LinkList s = new LNode;
		s->data = data;
		s->next = NULL;
		r->next = s;							//令第n个结点的前一个结点r指向新结点s
		s->next = p;							//再令s的下一个为第n个结点p
	}

}

//销毁链表
void DirstLink(LinkList& HeadNode)
{
	LinkList p = HeadNode;
	while (p != NULL)				//通过循环进行每一个结点的内存释放
	{
		LinkList q = p;
		p = p->next;
		delete q;
	}
	HeadNode = NULL;				//释放完后首指针指向NULL
}

双链表代码

#include<iostream>

using namespace std;


typedef int Elemtype;
//双向链表结构
typedef struct node
{
	int data;
	struct node* next, * last;
}LNode,*Link;
//链表生成
Link CreatLink(int size);
//头插入
void HeadInsert(Link& headnode, Elemtype data);
//尾插入
void TailInsert(Link& node, Elemtype data);
//任意插入
void InsertLink(Link& node, Elemtype data, int n);
//删除指定结点
void DelNode(Link& node, int n);
//销毁链表
void DirstLink(Link& node);

//int main()
//{
//	Link p = CreatLink(2);
//
//	InsertLink(p, 99, 1);
//	InsertLink(p, 99, 2);
//	InsertLink(p, 99, 4);
//	DelNode(p, 1);
//	DelNode(p, 1);
//	DelNode(p, 2);
//	Link q = p;
//	while (q != NULL)
//	{
//		cout << q->data << " ";
//		q = q->next;
//	}
//
//
//
//	return 0;
//}

//生成大小为size的链表并存入数据
Link CreatLink(int size)
{
	Link p, q, list = NULL;
	p = q = NULL;
	for (int i = 0; i < size; i++)				//存入size次数据
	{
		Elemtype data;
		cin >> data;
		p = new LNode;
		p->data = data;
		p->last = p->next = NULL;				//将每次中间过程的空间在生成的时候都前后指针置空
		if (list == NULL)						//防止后面忘记而出现访问空指针
		{
			list = p;							//如果list指针为空说明是第一次开辟空间
		}										//因此将首地址赋给list
		else
		{										//如果不是第一次开辟空间
			q->next = p;						//将空间q的后指针域指向它后面的空间p
			p->last = q;						//将空间p的前指针域指向前面的空间q
		}
		q = p;									//令q向后移动一次
	}
	return list;
}

//链表头插入
void HeadInsert(Link& headnode,Elemtype data)
{
	if (headnode == NULL)									//如果插入时头结点为空将对头结点进行空间赋值
	{
		headnode = new LNode;
		headnode->data = data;
		headnode->last = headnode->next = NULL;
	}
	else
	{														//头结点不为空则将新结点前指针域置空,后指针域指向
		Link p = new LNode;									//之前的头结点
		p->data = data;
		p->last = NULL;
		p->next = headnode;
		headnode->last = p;
		headnode = p;										//再令指向之前的头结点的指针移动到新生成的结点
	}
}

//链表尾插入
void TailInsert(Link& node,Elemtype data)
{
	Link q = node;
	while (q->next != NULL)							//遍历链表找到最后一个结点q
	{
		q = q->next;
	}
	Link p = new LNode;
	p->data = data;
	p->next = NULL;									
	p->last = q;									//将p的前指针域连上q
	q->next = p;									//将q的后指针域连上p
}
//将数据插入到链表指定位置n
//   1<= n <=max
//如果 n>max则会插入到链表尾
void InsertLink(Link& node, Elemtype data, int n)	
{
	if (n <= 0)										//判断插入的地方是否在范围内
	{
		cout << "插入位置非法!" << endl;
		exit(0);
	}
	else
	{												
		int i = 1;
		Link p = new LNode, q = node, r = node;
		while (i != n && q!= NULL &&r!= NULL)		//找到插入的位置n的结点
		{
			r = q;									//r始终是q的前一个结点
			q = q->next;
			i++;
		}
		p->data = data;
		p->last = p->next = NULL;
		if (n == 1)									//如果是链头则与头插入一样
		{
			p->next = node;
			node->last = p;
			node = p;
		}
		else if (q == NULL)							//q==NULL则表明插入到链尾
		{
			if(r!=NULL)
				r->next = p;
			p->last = r;
		}
		else
		{											//插入的不是链头也不是链尾
			p->next = q;							//要将 p 插入到 r q的中间
			q->last = p;							//先让p的后面连上q
			p->last = r;							//再让q的前面连上p
			r->next = p;							//再让p的前面连上r,r的后面连上p
		}
	}
}
//删除第n个结点
//  1<= n <=max
void DelNode(Link& node, int n)					
{
	if (n <= 0)							//要删除的结点位置必须合法
	{
		exit(0);
	}
	else							
	{
		int i = 1;
		Link q = node;
		while (i != n && q != NULL)		//定义i来寻找第n个结点
		{								//删除最后一个结点
			q = q->next;
			i++;
		}
		if (n == 1)						//如果删除的结点是首结点
		{
			Link p = node;				//记住首结点的地址
			node = node->next;			//令首结点的指针指向第二个结点,因此第二个结点成为了首结点
			node->last = NULL;
			delete p;					//释放首结点
		}
		else if (q == NULL)				//q为NULL说明删除的第n个结点已经超过了链表已有数量,因此异常退出
		{
			exit(0);
		}
		else if(q->next == NULL)		//q的next为空,说明此时q为最后的结点
		{
			q->last->next = NULL;		//将q的前一个结点的next置为NULL再删除q结点即可
			delete q;
		}
		else							//q此时既不是首结点已不是尾结点,并且在链表中
		{
			q->last->next = q->next;	//将q结点的前一个结点的next指向q的下一个结点
			q->next->last = q->last;	//将q结点的后一个结点的last指向q的前一个结点
			delete q;					//这样就完成了q的前后结点重新连接,q进行释放
		}
	}
}
//链表销毁
void DirstLink(Link& node)
{
	Link p = node, r = NULL;
	while (p != NULL)
	{
		r = p;			//r始终是p的前一个结点,p更新到下一个结点时就可以对r,即p的前一个结点进行释放
		p = p->next;
		delete r;
	}
	node = NULL;		//最后将链表首地址指向NULL
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值