#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;
}
