c++实现链表的增删改查----对LeetCode的链表复习

单链表操作实现
本文介绍了一个简单的单链表类的实现,包括创建、遍历、插入、删除等基本操作,并提供了完整的C++代码示例。
#include<iostream>
#include<vector>
using namespace std;

typedef int DataType;//定义数据类型,用后面的来表示前面的

#define Node ElemType//将Node重定义为ElemType
#define ERROR NULL


//定义一个节点,定义数据和节点指针
class Node
{
public:
	int data;
	Node* next;
};

//声明一个链表类
class LinkList
{
public:
	LinkList();
	LinkList(LinkList &list);  //复制构造函数,传入的是引用
	~LinkList();
	void CreateLinkList(int n);   //创建一个单链表
	void TravalLinkList();        //遍历线性表
	int GetLength();              //获取线性表长度
	bool IsEmpty();               //判断单链表是否为空
	ElemType* Find(DataType data); //查找节点,f返回的是指向节点的指针
	void InsertElemAtEnd(DataType data);            //在尾部插入指定的元素
	void InsertElemAtIndex(DataType data, int n);//在指定的位置n插入指定的元素data
	void InsertElemAtHead(DataType data);           //在头部插入指定元素
	void DeleteElemAtEnd();//在尾部删除元素
	void DeleteAll();    //删除所有数据
	void DeleteElemAtdata(DataType data); //删除指定的数据
	void DeleteElemAtPoint(int n);//删除指定位置的数据
	void DeleteElemAtHead();      //在头部删除节点 
private:
	ElemType* head;//定义一个头结点,指针指向第一个结点,数据域为空
};


//构造函数
LinkList::LinkList()
{
	head = new ElemType;//新建一个结点
	head->data = 0;//数据域设置为0
	head->next = NULL;//将指针指向空
}

//复制构造函数
LinkList::LinkList(LinkList &list)
{
	ElemType* phead = new ElemType;//声明一个头结点
	phead->next = NULL;//将头结点先指向空
	ElemType* p = list.head->next;//将原来的链表的第一个结点地址赋值给p
	while (p)
	{
		ElemType* qtemp = phead;//表示新链表的当前结点
		ElemType* q = new ElemType;//新建一个结点
		q->data = p->data;//将原来的链表的第一个结点的值赋值给新链表第一个结点
		qtemp->next = q;//将q放在新的链表的后面
		qtemp = q;//将q设置当前的结点
		qtemp->next = NULL;
		p = p->next;
	}
}

//析构函数,将头结点也删除
LinkList::~LinkList()
{
	ElemType* p = head;//定义p和q都为空
	ElemType* q = NULL;
	//p = head->next;//p表示第一个结点
	while (p)
	{
		q = p->next;//q表示第一个结点
		delete p;//删除头结点
		p = q;//再讲刚刚赋值的第一个结点赋值给p
	}
}

//创建一个n个数据的链表
void LinkList::CreateLinkList(int n) 
{
	cout << "请输入链表结点的个数:";
	ElemType *pnew, *ptemp;//定义一个新建的结点,和一个当前的结点
	ptemp = head;//将头结点表示当前结点
	cin >> n;
	if (n < 0)
	{
		cout << "你输入的个数不对,请输入大于0的正整数" << endl;
		exit(EXIT_FAILURE);
	}
	for (int i = 0; i < n; i++)
	{
		pnew = new ElemType;//新建一个结点
		cin >> pnew->data;//输入新建结点的值
		pnew->next = NULL;//将新建的结构指向空
		//将新建的结构放在当前结点的后面
		ptemp->next = pnew;//将新建结点放在当前结点的后面,第一次也就是放在头结点的后面
		ptemp = pnew;//将新的结点设置成当前结点
	}
}

//遍历线性表
void LinkList::TravalLinkList()
{
	if (head == NULL || head->next == NULL)
	{
		cout << "你输入链表是空" << endl;
	}
	ElemType *p = head;//新建一个结点,见头结点的地址给他
	while (p->next!=NULL)//如果括号内只是写p的话,就比p->next!=NULL多执行一步
	{
		p = p->next;//指向第一个结点
		cout << p->data<<" ";//输出第一个结点的数据
	}
	cout << endl;
}

//获取线性表长度
int LinkList::GetLength()
{
	if (head == NULL || head->next == NULL)
	{
		return 0;
	}
	ElemType *p = head;//新建一个结点,见头结点的地址给他
	int len = 0;
	while (p->next != NULL)//如果括号内只是写p的话,就比p->next!=NULL多执行一步
	{
		p = p->next;//指向第一个结点
		len++;
	}
	return len;
}

//判断单链表是否为空
bool  LinkList::IsEmpty()
{
	if (head == NULL || head->next == NULL)
	{
		return true;
	}
	else
	{
		return false;
	}
}

//在尾部插入指定的元素
void LinkList::InsertElemAtEnd(DataType data)
{
	//先遍历到链表的末尾
	ElemType *p = head;//新建一个结点,见头结点的地址给他
	while (p->next != NULL)//循环遍历到最后一个结点
	{
		p = p->next;
	}
	ElemType *pnew = new ElemType;//新建一个结点
	pnew->data = data;//将制定的元素赋值给新建的结点
	pnew->next = NULL;//将新建的结点指向NULL
	p->next = pnew;//插到链表的末尾

}

//在头部插入指定元素
void LinkList::InsertElemAtHead(DataType data)
{
	ElemType *p = head;//新建一个结点,见头结点的地址给他
	ElemType* pfirst = p->next;//将第一个结点的地址存储好
	ElemType *pnew = new ElemType;//新建一个结点
	pnew->data = data;
	pnew->next = pfirst;//将原先的第一个结点插入到新建的结点的后面
	p->next = pnew;//将新建的结点插入到头结点的后面
}

//在指定的位置n插入指定的元素data
void LinkList::InsertElemAtIndex(DataType data, int n)
{
	if (n == 0)//n==0的话就表示插在链表的头部
	{
		InsertElemAtHead(data);
	}
	else if (n == (GetLength() + 1))//插在尾部
	{
		InsertElemAtEnd(data);
	}
	else if (n > (GetLength() + 1))
	{
		cout << "您插入的位置超标啦!请重新插入" << endl;
	}
	else//在1~GetLength()之间插入
	{
		//先遍历找到n - 1的结点的位置
		int j = 1;
		ElemType *p = head;//新建一个结点指向头结点
		while (j < n)//遍历找到n-1个结点的位置
		{
			j++;
			p = p->next;
		}
		ElemType *pLast = p->next;//保存原来的n位置的结点
		ElemType *pnew = new ElemType;//新建一个结点
		pnew->data = data;//赋值
		pnew->next = pLast;//将原来的n位置的结点插入到新建结点的后面
		p->next = pnew;//将新建的结点插入到n-1位置的后面
	}
}

//在尾部删除元素
void LinkList::DeleteElemAtEnd()
{
	if (head == NULL || head->next == NULL)
	{
		cout << "链表已经为空,无法删除元素" << endl;
	}
	else
	{
		int len = GetLength();
		int j = 1;
		ElemType *p = head;//新建一个结点指向头结点
		while (j < len)//遍历找到len-1个结点的位置
		{
			j++;
			p = p->next;
		}
		ElemType *tail = p->next;//最后一个结点
		p->next = NULL;//将len-1个结点指向空
		tail->next = NULL;//将原来的最后一个结点的指向空
		delete tail;//释放最后一个结点的空间
	}
	
	
}

//删除所有数据
void LinkList::DeleteAll()
{
	if (head == NULL || head->next == NULL)
	{
		cout << "链表已经为空,不必再清空!" << endl;
	}
	else
	{
		ElemType* p = head->next;//定义p和q都为空
		ElemType* q = p;
		//p = head->next;//p表示第一个结点
		while (p != NULL)
		{
			q = p->next;//q表示第一个结点
			delete p;//删除头结点
			p = q;//再讲刚刚赋值的第一个结点赋值给p
		}
		head->next = NULL;//全都删除完毕以后将头结点指向空
	}
}

//在头部删除节点 
void LinkList::DeleteElemAtHead()
{
	ElemType* p = head;//头结点的指针
	ElemType* pSecond = p->next->next;//原来的第二个结点
	ElemType* pFirst = p->next;//原来的第一个结点
	head->next = pSecond;//将头结点指向原来的第二个结点
	pFirst->next = NULL;//将原来的第一个结点指向空
	delete pFirst;//释放第一个结点的空间
}

//删除指定的数据
void LinkList::DeleteElemAtPoint(int n)
{
	if (n == 0)
	{
		DeleteElemAtHead();//在头部删除数据
	}
	else if (n == GetLength())
	{
		DeleteElemAtEnd();//在尾部删除数据
	}
	else if (n > GetLength())
	{
		cout << "您删除的位置超标,无法删除!" << endl;
	}
	else
	{
		int j = 1;
		ElemType *p = head;//新建一个结点指向头结点
		while (j < n)//遍历找到n-1个结点的位置
		{
			j++;
			p = p->next;
		}
		ElemType *plastTwo = p->next->next;//将n+1个结点的位置存储起来
		ElemType * ptemp = p->next;//将第n个结点存储起来
		p->next = plastTwo;//将n-1个结点连接上n+1个结点
		ptemp->next = NULL;//将第n个结点指向空
		delete ptemp;//释放第n个结点的空间
	}
}

//查找节点,f返回的是指向第一个data节点的指针
ElemType* LinkList::Find(DataType data)
{
	ElemType *p = head->next;//新建一个结点指向头结点
	if (p == NULL) 
	{                          
		//当为空表时,报异常
		cout << "此链表为空链表" << endl;
		return NULL;
	}
	else
	{
		while (p != NULL)
		{
			if (p->data == data)//如果有数据和链表中的数据相同的话就返回链表的指针
			{
				return p;
			}
			p = p->next;//指向下一个结点
		}
		if (p == NULL)//如果遍历完都没有数据相同的话就返回空
		{
			return NULL;
		}
	}
	
}

//删除指定的数据
void LinkList::DeleteElemAtdata(DataType data)
{
	ElemType* ptemp = Find(data);
	if (ptemp == head->next)//如果是第一个结点的话就删除
	{
		DeleteElemAtHead();
	}
	else if (ptemp == NULL)//如果没有指定的数据的话
	{
		cout << "链表中没有指定的数据可以删除!" << endl;
	}
	else
	{
		while (ptemp != NULL)
		{
			ElemType * p = head;          //p指向头结点
			while (p->next != ptemp)//循环遍历找到ptemp前面的一个结点的指针
			{
				p = p->next;
			}
			p->next = p->next->next;//将ptemp前面的结点链接上ptemp的后面一个结点
			ptemp->next = NULL;//将当前的结点指向空
			delete ptemp;//释放空间
			ptemp = Find(data);//第一次遍历完以后再剩下的链表中寻找符合条件的结点的位置
		}
	}
}
int main()
{
	LinkList list;
	list.CreateLinkList(4);
	/*list.TravalLinkList();
	int len = list.GetLength();
	cout << "链表的长度是:" << len << endl;*/
	/*list.InsertElemAtEnd(5);
	list.InsertElemAtHead(6);*/
	/*list.InsertElemAtIndex(6 , 3);*/
	/*list.DeleteElemAtEnd();
	list.TravalLinkList();
	list.DeleteAll();
	list.TravalLinkList();*/
	/*list.DeleteElemAtHead();*/
//	list.DeleteElemAtPoint(2);
	//list.DeleteElemAtdata(2);
	list.TravalLinkList();
	return 0;
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值