链表是指使用链接的方式存储的线性表,一般一个单链表结点由数据域和指针域两个域组成如图1所示,其中数据域data存放该结点的数据域的值,指针域next存放该结点的后继结点的地址信息。
2、单链表的头文件
#pragma once
#include<iostream>
#include<string.h>
struct StuNode//代表学生的节点
{
int ID;//学号
char name[10];//姓名
struct StuNode *next;
};
typedef struct StuNode StuNode;
class SLList
{
private:
StuNode *head;//表头指针
int length;
public:
SLList();
~SLList(void);
bool IsEmpty(void)const { return head->next ==NULL; }//判断链表是否为空
int Length()const { return this->length; }//返回链表长度
int Find(StuNode &item)const;//根据学生的学号查找学生
void DisPlay();//打印出链表中所有的学生信息
void Delete(StuNode &item);//删除链表
void Insert(const StuNode &item);//插入链表
};
3、单链表的.ccp文件
#include<string.h>
#include"sllist.h"
#include<iostream>
using namespace std;
SLList::SLList()
{
this->head = NULL;
this->length = 0;
}
SLList::~SLList()
{
StuNode* temp;
for (int i = 0; i < this->length; i++)
{
temp = head;
head = head->next;
delete temp;
}
}
int SLList::Find( StuNode & item) const
{
StuNode *temp = head;
for (int i = 0; i < this->length; i++)
{
if (temp->next->ID == item.ID)
{
cout <<temp->next->name<<"的位置为:" << i << endl;
return i;
}
temp = temp->next;
}
cout << "没有该学生" << endl;
return -1;
}
void SLList::DisPlay()
{
cout << "人员信息:" << endl;
cout << endl;
StuNode *temp = head;
while (temp->next != NULL)
{
cout << "学号:" <<temp->next->ID<< endl;
cout << "姓名:" << temp->next->name << endl;
temp = temp->next;
cout << endl;
}
}
void SLList::Insert(const StuNode &item)
{
if (this->head == NULL)/*头节点插入数据*/
{
StuNode *hemp = new StuNode;
this->head = hemp;
StuNode *node = new StuNode;
strcpy(node->name, item.name);
node->ID = item.ID;
this->head->next = node;
node->next = NULL;
this->length++;
return;
}
else//尾节点插入数据
{
StuNode *temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
StuNode *node = new StuNode;
strcpy(node->name, item.name);
node->ID = item.ID;
temp->next = node;
node->next = NULL;
this->length++;
return;
}
cout << "插入数据出错" << endl;
}
void SLList::Delete(StuNode & item)//根据学号删除链表中的信息
{
int ret = 0;
ret = Find(item);
if (ret == -1)
{
cout << "没有该学生,无法删除" << endl;
return;
}
else if (ret == 0)//头节点删除
{
StuNode *temp = this->head;//
StuNode *stmp = temp->next;
this->head->next = stmp->next;
delete stmp;
this->length--;
return ;
}
else if (ret > 0 && ret < this->length)//中间删除
{
StuNode *temp = this->head;
for (int i = 0; i <ret; i++)
{
temp = temp->next;
}
StuNode *stemp = temp->next;//与上面的删除同理
temp->next = stemp->next;
delete stemp;
this->length--;
return;
}
else
{
//尾节点删除
StuNode *temp = this->head;
while (temp->next->next != NULL)
{
temp = temp->next;
}
StuNode *ptem = temp->next;//保存住尾节点的地址
temp->next = NULL;
delete ptem;
this->length--;
return;
}
cout << "删除出错" << endl;
}
4、测试程序
#include"sllist.h"
#include<iostream>
using namespace std;
int main()
{
StuNode s1,s2,s3;
s1.ID = 20201;
strcpy(s1.name, "张三");
s2.ID = 20202;
strcpy(s2.name, "李四");
s3.ID = 20203;
strcpy(s3.name, "王五");
SLList a;
a.Insert(s1);
a.Insert(s2);
a.Insert(s3);
a.Find(s2);//查找李四 结点的位置是从0开始所以李四在结点的位置是1
a.DisPlay();//展示链表中存储的所有信息
cout << endl;
a.Delete(s2);// 删除李四
a.Find(s2);//查找链表否还有李四
a.DisPlay();
return 0;
}
5、测试的效果如图2所示
6、总结
刚开始写单链表的时候给头结点this->head=NULL初始化后,没有创建一个新结点,而是直接拿来用,程序一直运行不正确、之后在调试后才发现没有给头结点分配地址,这个错误浪费了好长时间,对于新手来说使用链表时要记得对头结点分配地址如下步骤
if (this->head == NULL)/*头节点插入数据*/
{
StuNode *hemp = new StuNode;//将原来this->head=NULL
this->head = hemp;//使用new 重新创建一个结点复制给head
}