线性表的链式存储-单链表,可以解决顺序表需要大量连续存储单元的缺点,但是由于增加了指针域,所以也存在浪费存储空间的缺点,不具备随机存取的特点,查找时,必须遍历链表。
头结点:带头结点的链表的第一个结点
头结点一般不存储信息
含有头结点和不含头结点的区别:
①第一个含有数据的结点实际为链表的第二个结点,简单来说就是方便了插入删除等操作,不用在进行特殊处理。
②含有头结点,无论单链表是否为空,头指针始终指向头结点,就是链表是否为空已经不重要了。
1.含有头结点的头插法
头插法:每次生成的新结点都插入到头结点之后,也就是放在表头,比如,本来链表里的数据是:2 1 3,然后插入4,此时就变成了,4 2 1 3;时间复杂度,插入一次为O(1),单链表长为你,O(n)
2.不含头结点的头插法
不含头结点,当L为空时(记得初始化L=NULL),直接将新结点的地址赋给L,L!=NULL时,在头部插入新结点后,再将新结点的地址赋给L,(L作为第一个结点)。
3.含有头结点的尾插法
尾插法:一般增加一个尾指针t,始终指向尾结点,方便在最后一个结点后插入新的结点,如果不使用尾指针,就需要每次遍历链表,到表尾插入,时间复杂度大大增加;而含有尾指针的时间复杂度和头插法一样O(n)
4.不含头结点的尾插法
插入第一个结点时,将新结点的地址赋给L,再将L的地址赋给尾结点t,之后依次往表尾插入即可。
完整代码
#include<cstdio>
#include<iostream>
using namespace std;
typedef int ElemType;
typedef struct LNode{
ElemType data; //存储数据
struct LNode *next;
}*LinkNode;
LinkNode headCreateLNode(LinkNode &L){ //含有头结点的头插法
int e;
L = (LNode*)malloc(sizeof(LNode));
L->next = NULL;
LNode *s;
cin>>e;
while(e!=-1){
s = (LNode*)malloc(sizeof(LNode));
s->data = e;
s->next = L->next;
L->next = s;
cin>>e;
}
return L;
}
LinkNode noheadCreateLinkNode(LinkNode &L){ 不含头结点的头插
int e;
//L = (LNode *)malloc(sizeof(LNode));
//L->next = NULL;
LinkNode s;
cin>>e;
while(e!=-1){
s=(LinkNode)malloc(sizeof(LNode));
s->data = e;
s->next = NULL;
cout<<"hahaha\n";
if(L==NULL){
L=s;
}else{
s->next = L;
L = s;
}
cin>>e;
}
//L->next = NULL; //有了这行代码,L的下一个节点直接变成NULL,只能输出一个元素
return L;
}
LinkNode tailCreateLinkNode(LinkNode L){ //含有头结点的尾插
LinkNode s;
int e;
L = (LinkNode)malloc(sizeof(LNode));
LinkNode t = L; //尾结点
cin>>e;
while(e!=-1){
s = (LNode*)malloc(sizeof(LNode));
s->data = e;
t->next = s;
t = s;
cin>>e;
}
t->next = NULL;
return L;
}
void tailNoHeadNodeCreateLNode(LinkNode &L){ //这里不加头结点或者尾结点都需要遍历链表
LinkNode s,t;
int e;
if(L==NULL) cout<<"yes\n"; //新创建出来的 L3!=NULL
else {
cout<<"NO\n";
}
L=NULL;
cin>>e;
while(e!=-1){
s=(LinkNode)malloc(sizeof(LNode));
s->data = e;
s->next = NULL;
if(L==NULL){
L = s;
t = L;
}else{
t->next = s;
t = s;
}
cin>>e;
}
t->next = NULL; //t作为尾结点,最后指向NULL
}
void printLNode(LinkNode L){ //没有头结点的输出也不一样
L=L->next;
if(L==NULL){
cout<<"error\n";
}
while(L){
cout<<L->data<<" ";
L=L->next;
}
}
void printNoHeadNode(LinkNode L){ //没有头结点的输出也不一样
//L=L->next;
if(L==NULL){
cout<<"error\n";
}
while(L){
cout<<L->data<<" ";
L=L->next;
}
}
int main()
{
LinkNode L,L1,L2,L3;
L3 = NULL;
L1 = NULL;
//cout<<L<<" "<<L1<<" "<<L2<<" "<<L3<<endl;
headCreateLNode(L); //头结点头插
printLNode(L);
L1 = tailCreateLinkNode(L1); //头结点尾插
printLNode(L1);
L2 = noheadCreateLinkNode(L2);
printNoHeadNode(L2);
tailNoHeadNodeCreateLNode(L3);
printNoHeadNode(L3);
return 0;
}
如有错误,敬请指正!