链表是一种物理上
非连续、非顺序
的存储结构,数据元素之间的顺序是通过每个元素的指针
关联的。
链表的特点:
结点
(链表中每一个元素称为结点)组成,结点可以在运行时动态生成
每个结点
包括两个部分:一个是存储数据元素的数据域
,另一个是存储下一个结点地址的指针域
。
链表结构图:
单链表又分为有空头和无空头,下列操作在无空头的基础上进行
有空头的操作更加简便
创建结点结构体,定义头尾指针
#include
#include
using namespace std;
//结点结构体
struct Node{
int a;
struct Node *pNext;
};
//链表头尾指针
struct Node *g_pHead = NULL;
struct Node *g_pEnd = NULL;
将该结点的指向下一个的指针指向原有链表的头,然后将该结点定为新链表的头
//创建链表,在链表中增加一个数据 头添加
void AddListHead(int a) {
//创建一个结点
struct Node* pTemp = (struct Node*) malloc(sizeof(struct Node));
//节点数据进行赋值
pTemp->a = a;
pTemp->pNext = NULL;
//如果链表为空
if (NULL == g_pHead || NULL == g_pEnd) {
//空链表 既是头也是尾
g_pHead = pTemp;
g_pEnd = pTemp;
}
//不为空链表
else {
pTemp->pNext = g_pHead;//将该结点的下一个指向原有链表的头
g_pHead = pTemp; //将该结点定为为新链表的头
}
}
原有链表的尾的下一个指针指向该结点,将该结点定为新链表的尾。
//创建链表,在链表中增加一个数据 尾添加
void AddListEnd(int a) {
//创建结点
struct Node* pTemp = (struct Node*) malloc(sizeof(struct Node));
//节点数据进行赋值
pTemp->a = a;
pTemp->pNext = NULL;
//如果链表为空
if (NULL == g_pHead || NULL == g_pEnd) {
//空链表 既是头也是尾
g_pHead = pTemp;
g_pEnd = pTemp;
}
//不为空链表
else {
g_pEnd->pNext = pTemp;//原有链表的尾的下一个指针指向该结点
g_pEnd = pTemp; //原有链表的尾的下一个指针指向该结点
}
}
void ScanList() {
//定义中间指针
struct Node *pTemp = g_pHead;
while (pTemp != NULL) {
cout << pTemp->a << endl; //输出该结点的值
pTemp = pTemp->pNext;
}
}
//查询指定的结点
struct Node* SelectNode(int a) {
//定义中间指针
struct Node* pTemp = g_pHead;
while (pTemp != NULL) {
if (a == pTemp->a) {
return pTemp; //查询到,返回该结点的值
}
pTemp = pTemp->pNext;
}
return NULL; //未查询到返回值为NULL
}
指定位置插入结点
//指定位置插入结点
void AddListRand(int index, int a) {
//链表为空
if (NULL == g_pHead) {
cout << "链表没有节点" << endl;
return;
}
//找位置
struct Node* pt = SelectNode(index);
if (NULL == pt) {
cout << "没有指定节点" << endl;
}
//有此结点
//给a创建结点
struct Node* pTemp = (struct Node*)malloc(sizeof(struct Node));
//结点成员赋值
pTemp->a = a;
pTemp->pNext = NULL;
if (pt == g_pEnd) {
g_pEnd->pNext = pTemp;
g_pEnd = pTemp;
}
else {
pTemp->pNext = pt->pNext;
pt->pNext = pTemp;
}
}
//尾删除
void DeleteListEnd() {
//链表为空
if (NULL == g_pEnd) {
cout << "链表为空,无需释放" << endl;
return;
}
// 链表只有一个结点
if (g_pHead == g_pEnd) {
free(g_pHead); //释放该结点(删除该结点)
g_pEnd = NULL;
g_pHead = NULL;
}
else {
//链表有多个结点
struct Node* pt = g_pEnd;
//找到尾巴的前一个结点
struct Node* ptemp = g_pHead;
while (ptemp->pNext != g_pEnd) {
ptemp = ptemp->pNext;
}
ptemp->pNext = NULL;//将尾结点的上一个结点的下一个的指针指向NULL
g_pEnd = ptemp;
free(pt); //释放节点(删除该结点)
}
}
//头删除
void DeleteListHead() {
//链表为空
if (NULL == g_pHead) {
cout << "链表为空,无需释放" << endl;
return;
}
// 链表只有一个节点
if (g_pHead == g_pEnd) {
free(g_pHead); //释放该结点(删除该结点)
g_pEnd = NULL;
g_pHead = NULL;
}
//多个结点
else {
struct Node* pTemp = g_pHead;//定义中间指针记录原有链表的头
g_pHead = g_pHead->pNext;//将链表头设置为原链表的下一个
free(pTemp); //释放该结点(删除该结点)
}
//删除指定结点
void DeleteListRand(int a) {
//链表判断
if (NULL == g_pHead) {
cout << " n o" << endl;
return;
}
struct Node* pTemp = SelectNode(a);//调用查询函数,查询值为a的结点,并赋值给中间结点pTemp
// 无
if (NULL == pTemp) {
cout << "查无此节点" << endl;
return;
}
//找到了
//只有一个结点
if (g_pHead == g_pEnd) {
free(g_pHead);
g_pHead = NULL;
g_pEnd = NULL;
}
//两个结点
else if (g_pHead->pNext == g_pEnd) {
if (g_pHead == pTemp) {//如果头为指定结点
DeleteListHead();//调用函数删除头结点
}
if(g_pEnd == pTemp){//如果尾为指定节点
DeleteListEnd();//调用函数删除尾结点
}
}
//多个结点
else {
if (g_pHead == pTemp) {//如果头为指定结点
DeleteListHead();//调用函数删除头结点
}
else if (g_pEnd == pTemp) {//如果尾为指定节点
DeleteListEnd();//调用函数删除尾结点
}
else {
//创建中间结点
struct Node* ptemp = SelectNode(a);//调用查询函数,查询值为a的结点,并赋值给中间结点pTemp
//找到之后
ptemp->pNext = pTemp->pNext;
free(pTemp); //释放该结点
}
}
}
void freeList() {
struct Node* pTemp = g_pHead;
while (pTemp != NULL) {
struct Node* pt = pTemp;
pTemp = pTemp->pNext;
free(pt);
}
//头尾清空
g_pHead = NULL;
g_pEnd = NULL;
}
emmmm 单链表的基操希望能够对你有帮助。。。。加油
单链表的基本操作的汇总见下篇博客呦。