(本文用来捋请单链表的基本操作)
单链表的基本操作:
(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;
}