单链表的基本操作

(本文用来捋请单链表的基本操作)

单链表的基本操作:

(1)单链表的定义:

class Node //节点类
{
public:
	int data;
	Node *pNext;
};

class LinkList //单向链表类
{
public:
	LinkList()//头节点不参与计数
	{
		head = new Node;
		head->data = 0;
		head->pNext = NULL;
	}
	~LinkList(){delete head;}//析构函数
	void CreatLinkList(int n);	//创建链表
	int GetLength();	//获取长度
	void TraverseLinkList();	//遍历链表
	void ReverseList(int n);	//逆序输出
	void InsertNode(int position,int d);	//插入函数
	void DeleteNode(int position);//删除函数
	void DeleteLinkList();	//删除整个链表
	bool IsEmpty();//判断链表是否为空
private:
	Node *head;
};
(2)单链表的创立

单链表的创立,在创立链表时要注意节点个数只能为正整数(万一有哪个脑袋秀逗的家伙非要输入一个负数或者是浮点数呢 QAQ)所以要加入一个判断节点个数的的代码段,(小声bb:由于是菜鸟,所以用了“goto”,听说好多大佬都不推荐使用goto,以后会逐渐改正的,但是这个循环很简单,所以我用了goto神器,哈哈哈)

//判断节点个数是否为负数!!!!
L1:cin>>n;
	if (n<0)
    {
	   cout<<"输入节点个数错误!重新输入。"<<'\n';
	   goto L1;
    }
接下来就是正式创立链表了,首先要定义一个结点指针(ptemp)用来指向最后一个节点,再new一个新节点(pnew)用来存放数据。
步骤 :
  • 首先让ptemp指向头节点(也就是当前链表的最后一个节点)
  • 然后进入while循环赋值
  • 每次循环都要新建一个节点
  • 将数据输入新节点的数据域
  • 让ptemp节点指向空
  • 然后将ptemp节点指向新节点
  • 最后将ptemp节点赋值为最后一个节点也就是新节点
void LinkList::CreatLinkList(int n)
{

	   Node *pnew,*ptemp;//定义一个暂时存放指针的节点与要输入的新节点
	   ptemp = head;
	   cout<<"Please Input the Inteager:";
	   while (n-->0)
	   {
		   pnew = new Node;
		   cin>>pnew->data;
		   pnew->pNext = NULL;//将pnew节点的下一个节点置为NULL
							  //,因为pnew节点会成为最后一个节点
		   ptemp->pNext = pnew;//将ptemp的指针存放pnew节点的地址
		   ptemp = pnew;	   
	   }
  
}
(3)单链表的插入
(1)为了增强链表的鲁棒性,所以依然在插入元素之前进行判断插入元素位置的范围:
  • 判断位置输入是否正确只要判断是否小于0或者大于链表长度即可。

L2:cin >> position;
	if ( position < 0 || position > l.GetLength() + 1)//获取长度函数之后会提及
    {
	   cout<<"输入位置错误!重新输入"<<'\n';
	   goto L2;
    }
    
(2)接下来就是正式插入元素的过程:
  • 定义两个结点指针,一个(pnew)用来存放要插入的节点,一个(ptemp)用来指向插入节点的前驱

  • 先将ptemp节点指向头节点,再为新节点分配一个空间,然后将要插入的数据存入新节点的数据域,然后将新节点指向NULL

  • 利用循环插入,因为是自己在捋请思路,所以就用文字描述一遍:

  • 首先将ptemp指针指向当前节点的下一位

  • 然后用新节点指向ptemp所指向节点的后置

  • 然后将temp节点指向新节点

void LinkList::InsertNode(int position,int d)
{

	   Node *pnew,*ptemp;//Node 一个pnew节点来暂时存储输入的数据
	   ptemp = head;     //把ptemp作为头节点,指针域为NULL
	   pnew = new Node; 
	   pnew->data = d;
	   pnew->pNext = NULL;//将pnew的指针域设置为NULL

	   while (position-- >= 0)//在当前位置往后移两位插入数据
		   ptemp = ptemp->pNext;//
		   pnew->pNext = ptemp->pNext;
		   ptemp->pNext = pnew;
   
}

核心算法:

 ptemp = ptemp->pNext;//
 pnew->pNext = ptemp->pNext;
 ptemp->pNext = pnew;  
(4)单链表节点的删除
1.依然要判断节点删除位置的范围,实现方法同插入,就不重复讲了,直接说删除的核心操作:
  • 定义一个节点指针,和一个保存要删除位置节点的指针

  • 进入循环

  • 指向当前节点的后置

  • 删除指针指向当前节点后置的后置

  • 然后用当前节点指向删除指针的后置(此时中间时要删除的节点)

  • delete 删除指针且后置为NULL


void LinkList::DeleteNode(int position)
{

    Node *ptemp = head,*pdelete;
    
	while (position-- > 0)
	 {
	   	 ptemp = ptemp->pNext;	//将ptemp节点指向他的后置
	 	 pdelete = ptemp->pNext;	//指向后置的后置
	 	 ptemp->pNext = pdelete->pNext;	//指向删除节点的后置
		  delete pdelete;			//释放删除节点的数据域
	 	 pdelete = NULL;			//将删除节点的数据域置为空
	 }
}
(5)单链表的删除
链表的删除比较简单,只需判断头节点后置是否为空就可以进行删除:
void LinkList::DeleteLinkList()
{
	Node *pdelete = head->pNext, *ptemp;
	while (pdelete != NULL)//如果头节点得的指针域不为空则继续删除
	{
		ptemp = pdelete->pNext;//指向删除节点的下一个节点
		head->pNext = ptemp;//将删除节点的前驱后置连起来
		delete pdelete;//释放删除节点
		pdelete = ptemp;//下一个节点赋值为删除节点
	}
}

核心思路:
要将删除节点的前驱后置连接起来,最后记得赋值。
核心代码:

ptemp = pdelete->pNext;//指向删除节点的下一个节点
head->pNext = ptemp;//将删除节点的前驱后置连起来起来
pdelete = ptemp;//下一个节点赋值为删除节点
(6)单链表的判空
判空操作很简单,就是判断头节点的后置是否为NULL,实现代码:
bool LinkList::IsEmpty() 
{
	if ( head->pNext == NULL)//如果头节点的指针域为NULL则链表为空
		return true;
	else
		return false;
}
(7)单链表的长度

长度的实现思路是和判空差不多,只需要再声明一个累加变量即可:

int LinkList::GetLength()
{
	Node *p = head->pNext;
	int n = 0;//累加变量
	while(p != NULL)
	{
		n++;
		p = p->pNext;
	}
	return n;
}
(8)单链表的输出
输出之前也要先判断当前节点后置是否为空,不为空才能输出:
void LinkList::TraverseLinkList()
{
	Node *p = head->pNext;//将头指针的指针域赋值给p
	while (p != NULL) //指针域不为空进入循环
	{
		cout<<p->data<<"  ";//输出指针数据域
		p = p->pNext;  //将下一个节点的指针域赋值给当前节点
	}
	cout<<'\n';
}

以上就是单链表的基本操作,接下来附上完整代码:

#include<iostream>
#include<stdlib.h>
using namespace std;

class Node //节点类s
{
public:
	int data;
	Node *pNext;
};

class LinkList //单向链表类
{
public:
	LinkList()//头节点不参与计数
	{
		head = new Node;
		head->data = 0;
		head->pNext = NULL;
	}
	~LinkList(){delete head;}
	void CreatLinkList(int n);				//创建链表
	int GetLength();						//获取长度
	void TraverseLinkList();				//遍历链表
	void ReverseList(int n);				//逆序输出
	void InsertNode(int position,int d);	//插入函数
	void DeleteNode(int position);			//删除函数
	void DeleteLinkList();					//删除整个链表
	bool IsEmpty();							//判断链表是否为空
private:
	Node *head;
};


void LinkList::CreatLinkList(int n)
{

	   Node *pnew,*ptemp;//定义一个暂时存放指针的节点与要输入的新节点
	   ptemp = head;
	   cout<<"Please Input the Inteager:";
	   while (n-->0)
	   {
		   pnew = new Node;
		   cin>>pnew->data;
		   pnew->pNext = NULL;//将pnew节点的下一个节点置为NULL
							  //,因为pnew节点会成为最后一个节点
		   ptemp->pNext = pnew;//将ptemp的指针存放pnew节点的地址
		   ptemp = pnew;	   
	   }
  
}

int LinkList::GetLength()
{
	Node *p = head->pNext;
	int n = 0;
	while(p != NULL)
	{
		n++;
		p = p->pNext;
	}
	return n;
}

void LinkList::TraverseLinkList()
{
	Node *p = head->pNext;//将头指针的指针域赋值给p
	while (p != NULL) //指针域不为空进入循环
	{
		cout<<p->data<<"  ";//输出指针数据域
		p = p->pNext;  //将下一个节点的指针域赋值给当前节点
	}
	cout<<'\n';
}

void LinkList::ReverseList(int n)
{
	Node *p = head->pNext;//将头指针的指针域赋值给p
	int *a = new int[n];
	while (p != NULL) //指针域不为空进入循环
	{
		for (int i=0; i<n; i++)
		{
		 a[i] = p->data ;//将指针数据域赋值给一个数组
		 p = p->pNext;  //将下一个节点的指针域赋值给当前节点
		}
	}
	for (int j=n-1; j>=0; j--)//逆序输出这个数组
	{
		cout<<a[j]<<" , ";
	}
	cout<<'\n'; 
}

void LinkList::InsertNode(int position,int d)
{

	   Node *pnew,*ptemp;//Node 一个pnew节点来暂时存储输入的数据
	   ptemp = head;     //把ptemp作为头节点,指针域为NULL
	   pnew = new Node; 
	   pnew->data = d;
	   pnew->pNext = NULL;//将pnew的指针域设置为NULL

	   while (position-- >= 0)//在当前位置往后移两位插入数据
		   ptemp = ptemp->pNext;//
		   pnew->pNext = ptemp->pNext;
		   ptemp->pNext = pnew;
   
}

void LinkList::DeleteNode(int position)
{

	   Node *ptemp = head,*pdelete;
	   while (position-- > 0)
		   ptemp = ptemp->pNext;	//将ptemp节点指向他的后置
		   pdelete = ptemp->pNext;	//指向后置的后置
		   ptemp->pNext = pdelete->pNext;	//指向删除节点的后置
		   delete pdelete;			//释放删除节点的数据域
		   pdelete = NULL;			//将删除节点的数据域置为空
   
}

void LinkList::DeleteLinkList()
{
	Node *pdelete = head->pNext, *ptemp;
	while (pdelete != NULL)//如果头节点得的指针域不为空则继续删除
	{
		ptemp = pdelete->pNext;//指向删除节点的下一个节点
		head->pNext = ptemp;//将删除节点的前驱后置连起来
		delete pdelete;//释放删除节点
		pdelete = ptemp;//下一个节点赋值为删除节点
	}
}

bool LinkList::IsEmpty() 
{
	if (head->pNext == NULL)//如果头节点的指针域为NULL则链表为空
		return true;
	else
		return false;
}

int main()
{
	LinkList l;
	int position = 0, value = 0, n = 0;
	bool flag = false;

	cout<<"Pleass input the Inteager Num:";
L1:cin>>n;
	if (n<0)
    {
	   cout<<"输入节点个数错误!重新输入。"<<'\n';
	   goto L1;
    }
	l.CreatLinkList(n);

	cout<<"Len: "<<l.GetLength()<<'\n'<<" >>Reverse Print:";
	l.ReverseList(n);

	cout << "Please Insert the  Pos :";
L2:cin >> position;
	if (position<0 || position>l.GetLength() + 1)
    {
	   cout<<"输入位置错误!重新输入"<<'\n';
	   goto L2;
    }
	cout << "Please Insert the  Num :";
	cin>> value;
	l.InsertNode(position,value);

	cout << ">>Len:"<<l.GetLength()<<" Data : ";
	l.TraverseLinkList();

	cout << "Please Del a Num:";
L3:cin >> position;
	if (position<0 || position>l.GetLength())
	{
		cout<<"输入位置错误!重新输入"<<'\n';
		goto L3;
    }
	l.DeleteNode(position);

	cout << " Len:"<<l.GetLength()<<" Data : ";
	l.TraverseLinkList();

	l.DeleteLinkList();
	flag = l.IsEmpty();
	if (flag)
		cout << "删除链表成功!" << endl;
	else
		cout << "删除链表失败!" << endl;
 
	return 0;
}

如果还是不懂,请点击这行蓝字参考大神的回答~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值