提示,可以根据目录,可以从 单链表的插入 删除——单链表的查找——单链表的建立这样的顺序进行学习!!!
单链表的建立
单链表的建立主要包括两种建立方法:头插法与尾插法。
基本步骤如下:
- 初始化一个单链表
- 每次取一个数据元素,*插入到表尾/表头 *(导致于头插法,尾插法)
头插法建立单链表
(带头结点的的单链表)
该方法从一个空表开始,生成新结点,并将读取到的数据存放在新结点的数据域中,然后将新结点插入到当前链表的表头,即头结点之后。
本质————是对头结点的后插操作
基本思路
- 初始化一个单链表
- 利用while循环{每次取一个数据元素e;调用一次后插法——InsertNextNode(L,e)}
代码实现
typedf struct LNode{
//定义单链表结构类型
ElemType data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//函数功能——头插法建立单链表
LinkList List_HeadInsert(LinkList &L){
//逆向建立单链表
LNode *s;
int x;
L = (LinkList)malloc(sizeof(LNode)) //创建头结点
L->next=NUll; //保证头指针是不会指向脏数据的,初始化为空链表
scanf("%d",&x); //输入结点的值
while(x!=99999){
//只有当输入x为99999时,循环无法进行,否则可以进行————即输入99999代表着结束
s=(LNode*)malloc(sizeof(LNode)); //申请新结点
s->data=x; //新结点的数据域被x覆盖
s-next=L->next; //将新结点链接在头指针的后继结点
L->next=s; //新结点插入表中,L为头指针
scanf("d",&x);
}
return L;
}
效果:
问题:若没有头结点,该如何理解头插法的修改?
答:没有了头指针,每次插入新结点后,需要将其指针指向单链表指针L
提示:链表的逆置可以考虑头插法的方法!
尾插法建立单链表
(带头结点的单链表)
法一:
- 初始化一个单链表;
- 利用按位序插入算法;
- 设置变量length来记录链表长度
- 每次都要循环,每取一个元素,按位序插入算法用一次,length++,时间复杂度为O( n 2 n^{2} n2)。
法二:
利用后插操作,设置一个表尾指针,每次更新,使得这个指针指向单链表的最后一个结点。
方法原理:
将新结点插入到当前链表的表尾,为此必须增加一个指针,使其始终指向当前链表的尾结点。
代码实现
typedf struct LNode{
//定义单链表结构类型
ElemType data; //每个节点存放一个数据元素
struct LNode *next; //指针指向下一个节点
}LNode,*LinkList;
//初始化一个空的单链表(带头节点)
bool Initlist(LinkList &L){
L = (LNode *)malloc(sizeof(LNode));//分配一个头节点,此头结点不存储数据。
if(L=NULL) //内存不足,分配失败
return false;
L->next = MULL; //头节点之后暂时还没有节点
return true;
}
//函数:按位序插入,在第i个位置插入元素 e
bool ListInsert(LinkList &L,int i,ElemType e){
if(i<1)
return false; //插入位置不合法
LNode *p; //指针p指向当前扫描的结点;
int j=0; //当前p指向的是第几个结点,利用j来记录;刚开始p指向单链表的头节点;
P=L; //L指向的是头节点,头节点是第0个结点(不存数据)
while(p!=NULL&&j<i-1){
// 通过循环找到第i-1个结点,这也是本算法的主要的时间开销 :为O(n)
p=p->next;
j++;
}
if(p==NULL) //i值不合法,超出链表长度,说明第i-1个结点不存在
return false;
LNode *s=(LNode*),malloc(sizeof(LNode));//申请新结点
s->data=e; //在新结点中存入数据元素e
s->next =p->next; //将新结点的指针域发挥与*p的指针域一样的作用:指向第i个结点;
p->next=s; //将结点连接到p之后,我们假设的是第i-1个结点为*p;
return ture; //插入成功!
}
//函数功能:后插操作,在p结点之后插入元素e.
bool InsertNextNode(LNode *p,ElemType e){
if(p==NULL) //结点p不合法
return false;
LNode *s=(LNode*),malloc(sizeof(LNode));//申请新结点
if(s==NULL)// 内存分配失败 。某些情况有可能分配不足,也可以不考虑这一点
return false;
s->data=e; //在新结点中存入数据元素e
s->next =p->next; //结点p的下一个结点由新结点s来链接;
p->next=s; //将结点s链接到p之后;
return ture; //插入成功!
}
void test (){
LinkList L; //声明一个指向单链表的指针
//注意到此处并没有创建一个节点
//初始化一个空表
InitList(L);
//....后续代码。。。。
}