巩固知识,做下笔记,如有错误请指正
一.链式存储结构的创建
typedef struct Node{
Student data;
struct Node *next;
}Node,*LinkList;
- data 是结点的数据域,用来存放具体的数据,*next是指针型变量,用来存放下一个节点的地址
- *LinkList用来创建指针类型的变量,即创建指向节点的指针,例:LinkList p
- Node用来创建节点,例:new Node
- p=new Node是指将节点的地址赋给p,使指针P指向该节点
- 其实*LinkList p=Node *p,为了代码的可读性,以及方便对指针和节点的区分才设置两个名称
二.方法传值 & 的理解
int main(){
LinkList L;
InitList(L);
void InitList(LinkList &L){
L=new Node;
if(!L) return ;
L->next=NULL;
printf("Enter successfully!\n");
}
- 用LinkList创建指针变量L(即头指针或链表),L的值为链表的引用,而&可以获取变量的引用地址,所以用&L作为形参接收数值
三.单链表的具体操作
1.几个基本原则
- 使代码具有简约性(精简删除代码),统一性(特殊操作和一般操作代码尽量相同),排错性(错误的输入自动提示或返回)
- 插入等改变指针指向的的操作秉持先后再前的原则,以避免节点地址被覆盖的情况
- 无用的节点及时释放
- 必要时添加辅助指针降低操作难度 例:尾指针 (把头指针和移动指针p称为基本指针)
- 头节点的序号为0,首元节点的序号为1
2.头节点的作用
- 是链表在头节点后插入,删除和其他操作具有相同的代码,使代码具有统一
- 无论链表是否为空,头指针始终是指向头节点的非空指针,清空链表后再进行录入时,不必再对头指针 L=new Node
3.初始化
int InitList(LinkList &L){
L=new Node;//创建头节点,并将头节点的引用赋值给指针L,使指针L指向头节点
L->next=NULL;//头节点的指针域置为空
return 1;
}
创建了一个只有头指针和头节点的空表,头节点的数据域可以存数据也可以不存
stateDiagram-v2
[L] --> data|NULL
4.取值
int GetElem(LinkList &L,int i,ElemType &e){//ElemTpye是指所有类型,需替换为int,double等具体类型
LinkList p=new Node;
p=L->next; int j=1;
while(p&&j<i){
p=p->next; j++;
}
if(!p||j>i) return ;
e=p->data;
return 1;
}
因首元节点开始有数据,所以将移动指针p指向首元节点,从首元节点开始,使用while循环移动指针移动指针至想要获取的元素
5.查找
与取值操作相同,指针从首元节点出发
Node *LocatElem(LinkList &L,ElemType e){
LinkList p=new Node;
p=L->next;
while(!p&&p->data!=e){
p=p->next
}
return p;//若查找成功返回p,若不成功,这时p=p->next=NULL返回空
}
6.插入
与取值和查找不同,插入操作需要指针p从头节点开始出发,因为(1)插入操作的位置是ai-1和ai之间的位置。(2)而且插入操作需要改变被插入位置前后节点的引用,而链表很难获取前驱,很容易获取后继,所以指针p应当指向被插入位置的前一个节点。特殊的在首元节点前插入需要P指针指向头节点即P=L。
int ListInert(LinkList &l,int i,ElemType e){
//i插入的位置,e为插入位置的数据
LinkList p=new Node;
LinkList s=new Node;
p=L; j=0;//出发位置为0
while(p&&j<i-1){//while循环移动指针,若while循环中为p->next则指针不能移动至最后一个指针,最后一个节点前就不能插入
p=p->next;//若一直未能查到(i的值大于j-1),最后一次进入循环后,p的值变成NULL
h++;
}
if(!p||j>i-1) return 0;
s->data=e;
s->next=p->next;
p->nex=s;
}
7.删除
删除该节点即将前一节点的指针域置为空,然后删除释放该节点
int ListDelete(LinkList &L,int i){
LinkList p=new Node;
LinkList q;
p=L; j=0;
while(p->next&&j<i-1){//j=i-1控制循环次数即指针移动次数,指针所在位置是删除节点之前,永远比删除节点序号小1
p=p->next; j++;
}
if(!(->next)|j>-1) return 0;
q=p->next;
p->next=q->next;
delete q;
return 1
}
8.创建单链表
(1)前插法
在首元节点前插入数据
void CreatList_H(LinkList &L,int n){
L=new Node;
L->next=NULL;
for(int i=0;i<n;i++){
LinkList p=new Node;//创建新节点
cin>>p->data;
p->next=L->next;//若没有首元节点则新节点指针域为空
L->next-p;
}
}
(2)尾插法
在最后的节点后插入节点,需要引入辅助指针尾指针,尾指针始终指向最后一个节点
void CreatList_R(LinkList &L,int n){
L=new Node;
L->next=NULL;
LinkList s=new Node;//创建尾指针
s=L;
for(int i=0;i<n;i++){
LinkList p=new Node;
cin>>p->data;
s->next=p;//只考虑一个节点的指针指向,该句与下一句顺序可以相反
p->next=NULL;
s=p;//刷新s指向尾节点
先录入数据,再建立节点间的联系,最后将新节点地址赋给s刷新尾指针