首先我们从简单的开始讲,单链表,其余的双链表,循环链表也就是在这个基础上增加了更多的逻辑关系罢了。
单链表:
链表简而言之就是和数组不同,储存地址不是连续的地址空间,链式结构 指的是不用地址连续的存储单元去存储元素
是由每个独立的节点去构成的链式结构------在C中这个独立的节点我们用单个的结构体去表示:
例如:
//节点的结构体
struct node{
int volue;
struct node *next;
};
那么单链表怎么创建?如何把节点都串在一起呢?
这里的思想是我们创建了一个头指针和尾指针,有利于数据节点的存放,如果我们想每个数据都放在链表最后的话,我们就采用尾插法,放在前面的话就是头插法,这样最为方便,我们总不能在中间开始插入数据那样太麻烦了
增加一个节点:
尾插法:
头插法:
比如下面的示例就是用了尾插法:
//尾插法
tail->next=pnew;
tail=pnew;
代码案例(单链表的案例代码):
#include <iostream>
using namespace std;
//单链表的创建
//节点的结构体
struct node{
int volue;
struct node *next;
};
int main()
{
//定义一个数据数组
int buff[10]={0,1,2,3,4,5,6,7,8,9};
//创建头节点
struct node *head=NULL;
//创尾节点
struct node *tail=NULL;
for(int i=0;i<10;i++)
{
//创建节点
struct node *pnew=new struct node;
pnew->volue=buff[i];
pnew->next=NULL;
//判断节点
if(head==NULL)
{
//该节点就是头节点
head=pnew;
tail=pnew;
}
else
{
//不是头节点
//尾插法
tail->next=pnew;
tail=pnew;
}
}
//创建一个遍历指针
struct node *p=head;
//打印链表数据
while(p!=NULL)
{
cout<<"链表数据是:"<<p->volue<<endl;
p=p->next;
}
return 0;
}
说到这,对链表的基本操作还不知道,这里我介绍了一些基本操
遍历打印链表:(这里我们创建了一个遍历指针)
//创建一个遍历指针
struct node *p=head;
//打印链表数据
while(p!=NULL)
{
cout<<"链表数据是:"<<p->volue<<endl;
p=p->next;
}
插入一个节点:
步骤:
第一步 找到待插入的位置
第二步 插入操作
struct node * add_a_node(struct node *head, ElemType x, ElemType a)
{
//1.创建一个新的节点a,把数据写入节点中
//2.找到值为x的节点 -->遍历(定义一个遍历指针)
//3.找到了 就把新节点a插入(分情况讨论:前面插入、中间插入、末尾插入)
//4.没有找到 就尾插法
//5.将新链表返回
}
struct node * add_a_node(struct node *head, ElemType x, ElemType a)
{
//1.创建一个新的节点a,把数据写入节点中
struct node *pnew = malloc(sizeof(struct node));
pnew->data = a;
pnew->next = NULL;
//2.找到值为x的节点 --》遍历(定义一个遍历指针)
struct node *p = head; //遍历指针p
struct node *pre = NULL; //保存p的前一个
while( p )
{
if( p->data == x )
{
break; //找到了
}
pre = p;
p = p->next;
}
//3.找到了 就把新节点a插入(分情况讨论:前面插入、中间插入、末尾插入)
if( p != NULL )
{
if( p == head )
{
//头插法
pnew->next = head;
head = pnew;
}
else
{
//中间插入
pre->next = pnew;
pnew->next = p;
}
}
else //4.没有找到 ( p == NULL ), 就尾插法 ,另一种情况head是空链表 也是找不到x的
{
if( head == NULL ) //head是一个空链表
{
head = pnew;
}
else
{
//尾插法
pre->next = pnew;
}
}
//5.将新链表返回
return head;
}
删除一个节点:
步骤:
找到要删除的节点的位置 (遍历)
删除操作
struct node * delete_node(struct node * head, ElemType x)
{
//1.找到值为x的节点
struct node *p = head; //遍历指针
struct node *pre = NULL; //保存p的前一个
while( p )
{
if( p->data == x ) //找到了
{
//2.删除值为x的节点 (分情况讨论:前面、中间、末尾)
if( p == head ) //删除首节点
{
head = head->next;
p->next = NULL; //工程规范,释放前先把指针置NULL
free( p );
}
else //删除 中间 和 末尾节点 的情况
{
pre->next = p->next;
p->next = NULL;
free(p);
}
break;
}
else
{
pre = p;
p = p->next;
}
}
//3.将新链表返回
return head;
}