双向链表内结点的删除(4)

情况有三:

  • 情况1:删除链表的第一个结点

            (1) 将指向链表开始的指针head指向第二个结点.

            (2) 此时原链表的第二个结点将成为新链表的开始,并且将新链表开始结点的指针back设为NULL.

  • 情况2:删除最后一个结点

             将原链表的最后一个结点之前一个结点的指针from设为NULL.

  • 情况3:删除链表内中间结点

            (1) 将链表内指针ptr所指结点的前一个结点指针front指向指针ptr所指结点的下一个结点.

            (2) 将链表内指针ptr所指结点的最后一个指针back指向指针ptr所指结点的前一个结点.

 

双向链表内结点删除
 
   
#include " iostream "
#include
" stdlib.h "
using namespace std;


struct dlist // 双向链表结构声明
{
int data; // 结点数据
struct dlist * front; // 指向下一结点的指针
struct dlist * back; // 指向前一结点的指针
};
typedef
struct dlist dnode; // 双向链表新类型
typedef dnode * dlink; // 双向链表指针新类型


/* -----使用数组值创建双向链表---- */

dlink createdlist(
int * array, int len)
{

dlink head;
// 双向链表的指针
dlink before; // 前一节点的指针
dlink new_node; // 新结点的指针
int i;

/* ------创建第一个结点-------- */

/* --------分配结点内存-------- */
head
= (dlink)malloc( sizeof (dnode));
if ( ! head) // 检查内存指针
return NULL;
head
-> data = array[ 0 ]; // 创建结点内容
head -> front = NULL; // 设置指针初值
head -> back = NULL; // 设置指针初值
before = head; // 指向第一个结点


for (i = 1 ;i < len;i ++ ) // 用循环创建其他结点
{

/* --分配结点内存-- */
new_node
= (dlink)malloc( sizeof (dnode));
if ( ! new_node)
return NULL;
new_node
-> data = array[i]; // 创建结点内容
new_node -> front = NULL;
new_node
-> back = before; // 将新结点指向前结点
before -> front = new_node; // 新结点成为前结点
before = new_node;

}
return head;
}

/* --------释放双向链表的内存----------- */

void freedlist( dlink head)
{
dlink ptr;
// 存储目前结点指针
while (head != NULL) // 链表遍历循环
{
ptr
= head; // 保留目前结点指针
head = head -> front; // 指向下一个结点
free(ptr); // 释放目前结点内存
}

}

/* -------双向链表的输出-------- */

void printdlist( dlink head,dlink now)
{
while (head != NULL) // 链表遍历循环
{
if (head == now) // 输出目前结点数据
printf( " #%d# " ,head -> data); // 输出结点数据
else
printf(
" [%d] " ,head -> data); // 输出结点数据
head = head -> front; // 指向下一个结点
}
printf(
" \n " );
}

/* -------双向链表的结点删除-------- */

dlink deletenode(dlink head,dlink ptr)
{
if (ptr -> back == NULL) // 是否有前结点
{
/* ----情况1:删除第一个结点---- */
head
= head -> front; // 指向下一个结点
head -> back = NULL; // 设置指向前结点的指针
}
else
{
if (ptr -> front == NULL) // 是否指向下一个结点
{
/* ---情况2:删除最后一个结点--- */

ptr
-> back -> front = NULL; // 前结点指向NULL

}
else
{
/* ----情况3:删除中间结点---- */
ptr
-> back -> front = ptr -> front; // 前结点指向下一结点
ptr -> front -> back = ptr -> back; // 下一结点指向前结点
}
}
free(ptr);
// 释放删除结点内存
return head; // 返回链表起始指针
}

/* -------------使用选项来移动结点后,删除目前的结点且将列出链表内容-------------- */
int main()
{
dlink head ;
// 双向链表指针
dlink now = NULL; // 目前结点指针
int list[ 6 ] = { 1 , 2 , 3 , 4 , 5 , 6 };
int select; // 选择项1~4
head = createdlist(list, 6 );
if (head == NULL)
{
printf(
" 内存分配失败!n " );
exit(
1 );
}

while ( 1 )
{
if (now == NULL)

now
= head; // 目前指向第一结点
printf( " 链表内容是: " );
printdlist(head,now);
/* ---选项内容--- */
printf(
" [1]往下移动 [2]往回移动 [3]删除结点 [4]离开 ==> " );
scanf(
" %d " , & select);
switch (select)
{
/* ---往下移动-- */
case 1 : if (now -> front != NULL)
now
= now -> front; // 指向下一结点
else
printf(
" 在链表结尾\n " );
break ;

/* ----往回移动---- */
case 2 : if (now -> back != NULL)
now
= now -> back; // 指向前一结点
else
printf(
" 在链表开始\n " );
break ;


/* ----删除目前结点---- */
case 3 : if (head != NULL)
{
head
= deletenode(head,now);
now
= head; // 目前指向第一结点

}
else
printf(
" 链表是空的\n " );
break ;
/* ----------离开--------- */
case 4 : freedlist(head);
exit(
1 );
}
}
}

 

 

      

转载于:https://www.cnblogs.com/FCWORLD/archive/2010/11/19/1881961.html

删除带头结点双向链表的第i个节点时,首先要明白带头结点的链表的结构。带头结点双向链表有一个特殊节点,即头结点,它不存储有效数据,但链接了链表的第一个和最后一个元素。第i个节点是指从头结点开始计数的第i个节点,即不包括头结点本身。 删除第i个节点的一般步骤如下: 1. 检查i的有效性:确保i的值在链表的范围内(1 <= i <= 链表长度)。 2. 寻找第i个节点:从头结点出发,遍历链表直到找到第i个节点。由于带头结点,实际上我们需要找到第i+1个节点。 3. 调整指针: - 如果第i个节点存在,调整其前驱节点和后继节点的指针,使它们跳过第i个节点,直接相连。 - 如果第i个节点是第一个有效节点(即i=1),需要调整头结点指针指向第二个节点。 4. 删除节点:释放第i个节点所占用的内存空间。 5. 更新链表长度:如果需要的话,更新链表中元素的数量。 这是一个简单的代码框架,展示删除操作的逻辑: ```c typedef struct Node { int data; struct Node* prev; struct Node* next; } Node; void deleteNodeAtPosition(Node* head, int position) { if (position < 1 || head == NULL) return; // 检查i的有效性 Node* current = head; for (int i = 0; i < position && current != NULL; ++i) { current = current->next; } if (current == NULL) return; // 如果没有找到第i个节点,则返回 Node* prevNode = current->prev; Node* nextNode = current->next; if (prevNode != NULL) { prevNode->next = nextNode; // 前驱节点指向后继节点 } else { // 如果要删除的是第一个有效节点,则需要更新头结点 head = nextNode; } if (nextNode != NULL) { nextNode->prev = prevNode; // 后继节点指向前驱节点 } free(current); // 释放内存 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值