一、简单描述
如果要实现在双链表结点p->prior和p->next中删除结点p
结果:删除结点p
(图源:程杰《大话数据结构(溢彩加强版)》)
核心算法:
p->prior->next=p->next; //如图①,把p->next赋值给p->prior的后继
p->next->prior=p->prior; //如图②,把p->prior赋值给p->next的前驱
free(p); //释放结点p
二、详细步骤:
1.初始化指针和计数器
j初始化为1,用于记录当前遍历的节点位置
定义指针变量p,用于表示待删除的节点p
int j=1;
LinkList p;
p=*L;
2.遍历链表找到第i个位置节点
使用while循环,直到找到第i个位置或链表末尾
while(p->next&&j<i){
p=p->next;
++j;
}
3.判断插入位置是否合理
如果找到第i个结点或i=链表长度加1,证明插入合理
如果未找到第i个节点(则p=NULL)或i小于1,则插入不合理,返回错误信息
if(!p||i<1){
return ERROR;
}
4.删除结点p
p->prior->next=p->next; //把p->next赋值给p->prior的后继
p->next->prior=p->prior; //把p->prior赋值给p->next的前驱
free(p); //释放结点p
5.返回操作结果
return OK;
三、核心代码:
int ListInsert(LinkList *L,int i,ElemType e)
{
int j=1;
LinkList p;
p=*L;
while (p && j<i) /*寻找第 i 个节点*/
{
p=p->next;
++j;
}
if (!p || j>i)
return ERROR; /*第 i 个元素不存在*/
p->prior->next=p->next; //把p->next赋值给p->prior的后继
p->next->prior=p->prior; //把p->prior赋值给p->next的前驱
free(p); //释放结点p
return OK;
}
四、完整代码:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *prior;
struct Node *next;
} Node, *LinkList;
void deleteNode(LinkList *L, LinkList p) {
if (!p || !(*L)) {
printf("Invalid node or empty list.\n");
return;
}
// 调整前后连接关系
p->prior->next = p->next;
p->next->prior = p->prior;
// 释放节点内存
free(p);
}
// 打印链表内容
void printList(LinkList L) {
while (L) {
printf("%d ", L->data);
L = L->next;
}
printf("\n");
}
int main() {
// 创建一个简单的链表作为示例
LinkList L = (LinkList)malloc(sizeof(Node));
L->data = 1;
Node *node2 = (Node *)malloc(sizeof(Node));
node2->data = 2;
L->next = node2;
node2->prior = L;
Node *node3 = (Node *)malloc(sizeof(Node));
node3->data = 3;
node2->next = node3;
node3->prior = node2;
node3->next = NULL;
printf("Original list: ");
printList(L);
// 要删除的节点是 node2
deleteNode(&L, node2);
printf("List after deletion: ");
printList(L);
// 释放链表内存
while (L) {
Node *temp = L;
L = L->next;
free(temp);
}
return 0;
}