需求:删除单链表第i个位置的结点,并返回删除的结点值
- 带头结点的
思路:删除第i个,由于单链表不具有随机存取的特点,就要遍历整个单链表,找到位序为i-1的结点,然后改变i-1的指针指向,跳过i指向i+!,在使用free函数释放掉位序为i的结点,实现删除
bool ListDelete(LinkList &L,int i,int &e) {
if(i<1) {
return false;
}
LNode *p;
p=L;
int j=0;
while(p!=NULL && j<i-1) {
p=p->next;
j++;
}
if(p=NULL) {
return false;
}
LNode *q=p->next; // p当前是i-1位置的结点,p->next指向的是i位置的结点,声明一个指针变量存储一下i位置的结点
p->next=q->next; // p结点指向q结点的指针域中存储的下一结点,也就是i+1位置的结点
e=q->data;
free(q);
return true;
}
- 不带头结点的
思路:与带头结点的删除不一样的地方是,由于不带头结点,头指针L指向链表的第一个节点,当删除的位序为1时,就要改变头指针L的指向,所以要单独判断i=1时的情况,其余跟带头结点的一样
bool ListDelete_NoL(LinkList &L,int i,int &e) {
if(i<1) {
return false;
}
if(i==1) {
LNode *q=L; // 头指针L指向链表第一个结点,声明一个指针变量q用来存储链表的第一个结点
L=q->next; // q->next:q是第一个结点,那么q->next就表示q结点的指针域存储的下一结点的地址,即链表的第二个结点的地址,赋值给L,就是让头指针L指向链表的第二个结点
free(q); // 释放q结点,头指针L又指向原链表的第二个结点,那么就表示q结点被删,原2变成了1
}
LNode *p;
p=L;
int j=0;
while(p!=NULL && j<i-1) {
p=p->next;
j++;
}
if(p=NULL) {
return false;
}
LNode *q=p->next;
p->next=q->next;
e=q->data;
free(q);
return true;
}
需求:删除指定的p节点
- 指定节点的删除
思路:改变p结点前面那个结点的指向,再释放p结点即可,但是怎么拿到p结点的前一结点呢:虽然拿不到前一结点的信息,但是可以操作下一结点的信息,让下一结点的值给p结点,p结点的指针域在指向下一结点的指针域存储的地址,就达到了将p结点变成p结点下一结点的目的,此时再删除p结点的下一结点,就可以实行指定结点的删除了,毕竟此时p结点的数据域和指针域都已经变成了原p结点下一结点的数据域和指针域
bool deleteNode(LNode *p, int &e) {
if(p==NULL) {
return false;
}
LNode *q=p->next; // 声明一个指针变量用来存储p结点的下一结点
p->next=q->next;
p->data=p->next->data; // 注意:p结点的数据域想要拿到q结点的数据域,绝对不能用q->data去赋值,因为声明q的时候,q是作为指针变量去声明的,它返回的是LNode类型数据的指针,存储了一个内存地址,而没有存储数据域,所以要写出p->next->data,因为p>next表示p结点的下一结点,而p->next->data就表示p结点的下一结点的数据域
free(q);
}