精华内容
下载资源
问答
  • 这里是节选的我看完课程后自己再写一次的双链表里面的删除结点的一段代码 int delete_node(dlnode *pHeader,int data) { dlnode *p = pHeader; if(NULL == p) { return -1; } while(NULL != p->pNext)...

    这里是节选的我看完课程后自己再写一次的双链表里面的删除结点的一段代码

    int delete_node(dlnode *pHeader,int data)
    {
    	
    	dlnode *p = pHeader;
    	if(NULL == p)
    	{
    		return -1;
    	}
    	
    	while(NULL != p->pNext)
    	{
    		p = p->pNext;
    		if(p->data == data)
    		{
    			if (NULL == p->pNext)
    			{
    				// 尾节点
    				// p表示当前节点地址,p->pNext表示后一个节点地址,p->pPrev表示前一个节点的地址
    				p->pPrev->pNext = NULL;
    				//p->pPrev = NULL;			可以省略,因为后面整个都被销毁了
    				// 销毁p节点
    				//free(p);
    			}
    			else
    			{
    				p->pPrev->pNext = p->pNext ;//把被删除的结点的前结点的pNext与后结点连起来
    				p->pNext->pPrev = p->pPrev;	//把被删除的结点的后结点的pPrev与前结点连起来
    			//p->pPrev = NULL;
    			//p->pNext = NULL;
    			
    			}
    			free(p);
    			
    			return 0;	
    		}
    	}
    	
    	printf("未找到该结点\n");
    	return -1;
    }
    

    目前这段代码运行是正常的,已经找过课程代码对比修改过了
    说说问题所在吧
    1.我之前想的时候没有注意把这个函数写成一个有返回值的函数,写成了void类型,当然,那时候我也没有写return。但是想起课程里面说如果传进来的头结点是一个NULL的话那就会报错了,因为NULL的pNext是没有分配到的。所以在前面加上一个if来判断是否是NULL。
    这里if判断之后可以不加return的,但是如果要判定正确0错误-1这样的话最好就加上return 0 return -1,网上查过0代表正确-1代表有误(大概这样吧)如果有返回值的话函数的返回值类型就得写成相应的类型,不能是void了,这里的话就是int类型。

    2.可能是没有连贯着写这段代码的原因吧,我没注意到我最后main函数里面的是前插,比如说前插顺序是33 2 1,向后遍历出来的就是1 2 33了,所以当我删除的33的时候我还以为是删除的第一个结点,运行的时候出现了段错误,其实并不是这样,我删除的33是最后一个结点,即尾结点,这时候我的while循环里面是没有判断是否为尾结点这一个判断条件的,因为不加上的话,尾结点的pNext就是NULL了,不存在后面的->pPrev了,所以编译虽然没错,但是运行起来就会出现段错误。后面我从课程代码里面吧这个if判断尾结点的拉过来了,然后就没出现段错误了。

    总结一下:
    大体的思路还算是清晰的,起码删掉结点之后要怎么连接前后结点这些还是没问题的,但是前面的判断头结点是否为NULL,或者尾结点的判断,这些尽管在看课程的时候是懂的,但是过后自己再写一次的时候就没有注意到,可能当时的印象不深刻吧。通过这次自己再写一次之后印象深刻了很多,对很多的基础知识也得到了运用。

    继续加油!

    展开全文
  • [数据结构]双链表删除结点P的操作

    千次阅读 2014-08-14 15:07:05
    算法的思想就是:把P的前驱

    算法的思想就是:把P的前驱结点接上P的后继节点。然后P的后继节点的前驱节点指向P的前驱节点。这个时候P就被架空了。此时释放P.


    代码:

    void DDeleteNode(DListNode *p){
    		//假设*P非最后的尾结点
    		p->prior->next = p->next;//P的前置节点的后继节点指向P的后继节点
    		p->next->prior = p->prior;//P的后置节点的前驱节点指向P的前驱节点
    		free(p);//释放P
    	}


    展开全文
  • 双链表的插入我认为有点难理解,特别是...双链表有前驱结点,后驱结点 理解了p->next , p->next->prior ,以及 s->next 这些,那对双链表的插入就好理解了 一、双链表的插入 双链表插入的另一种...

    双链表的插入我认为有点难理解,特别是那些指针,p->next   ,  p->next->prior  ,以及  s->next  这些

    双链表有前驱结点,后驱结点

    理解了p->next   ,  p->next->prior  ,以及  s->next  这些,那对双链表的插入就好理解了

     

    一、双链表的插入

     双链表插入的另一种示意图

     

    二、双链表的删除

    有了以上的了解,那它的删除也好理解了

    结点删除的另一示意图(都差不多的,方便理解)

     

    双链表的结点指针的理解示意图

    转载于:https://www.cnblogs.com/yyp-20190107/p/11029111.html

    展开全文
  • 数据结构:双链表的创建,在P结点前后插入结点,删除P前后的结点以及P结点 提到链表的首元结点,我们首先想到的是head标志的结点,但其实head结点只是人为规定的,首元结点既可以定义为head也可以定义为end,尾元...

    数据结构:双链表的创建,在P结点前后插入结点,删除P前后的结点以及P结点

    提到链表的首元结点,我们首先想到的是head标志的结点,但其实head结点只是人为规定的,首元结点既可以定义为head也可以定义为end,尾元结点也是如此,即首元结点和尾元结点可以任意定义。

    有了以上的思想我们将结点看成火车的一节车厢,结点中的信息看成车厢中的货物,首元结点看作车头来看待链表。而双链表则可以看成有两个车头的火车,即首元结点和尾元结点都是车头,这样一来火车既可以正着开也可以逆着开,所以也就没有纯粹意义上的首元结点和尾元结点了,即首元结点和尾元结点等价。

    所以在双链表中要实现形如下图的两种关系:
    双链表的两种关系

    定义结构体

    与单链表相比应该多增加一个指针

    typedef struct node
    {
     int date;
     struct node * pr;
     struct node * next;
    }Node,*LinkList;

    链表初始化

    初始化时,为了表示方便,以head来表示首元结点,用end来表示尾元结点,同时这两个结点不用来储存信息,由于将head看作第一个结点,end看作最后的结点,所以head->pr=NULL,end->next=NULL

    void InitList(LinkList head,LinkList end)
    {
     head->next=end;
     end->next=NULL;
     end->pr=head;
     head->pr=NULL;
    }

    链表的创建

    void Creat(LinkList end,int n)
    {
     int i;
     LinkList node; 
     for(i=1;i<=n;i++)
     {
      node=(LinkList)malloc(sizeof(Node));
      node->date=i;
      /*这里采用的是尾插法,即插在数据的尾部,但要注意,尾元结点必须在链表尾部,其实质是在尾元结点前插入新结点*/ 
      node->next=end; 
      end->pr->next=node;
      node->pr=end->pr;
      end->pr=node; 
     }
    }

    从链表中取得信息

    这里仅以head结点为基准取得信息

    LinkList GetElem(LinkList head,int n)
    {
     LinkList h=head->next;
     int i;
     for(i=1;i<n;i++)
     h=h->next;
     return h; 
    }

    将S结点的信息插在P结点前

    void InsertBefore(LinkList P,LinkList S)
    {/*将S结点的信息插在P结点前*/ 
     S->pr=P->pr;
     P->pr->next=S;
     S->next=P; 
     P->pr=S;
    }
    

    将S结点的信息插在P结点后

    void InsertAfter(LinkList P,LinkList S)
    {/*将S结点的信息插在P结点后*/ 
     P->next->pr=S;
     S->pr=P;
     S->next=P->next;
     P->next=S;
    }

    删除P结点前的结点

    void DeletBefore(LinkList P)
    {
     LinkList Q;
     Q=P->pr;
     P->pr=Q->pr;
     Q->pr->next=P;
     free(Q);
    }

    删除P结点后的结点

    void DeletAfter(LinkList P)
    {
     LinkList Q;
     Q=P->next;
     P->next=Q->next;
     Q->next->pr=P;
     free(Q);
    }

    删除P结点

    void DeletItself(LinkList P)
    {
     LinkList Q,R;
     Q=P->pr;
     R=P->next;
     Q->next=R;
     R->pr=Q;
     free(P);
    }

    正序输出

    void Show(LinkList head)
    {
     LinkList h=head->next;
     while(h->next!=NULL)
     {
      printf("%d ",h->date);
      h=h->next;
     }
     printf("\n");
    }

    逆序输出

    void ReShow(LinkList end)
    {
     LinkList e=end->pr;
     while(e->pr!=NULL)
     {
      printf("%d ",e->date);
      e=e->pr;
     }
     printf("\n");
    }

    在主函数中验证是否正确

    int main()
    {
     LinkList head,end;
     head=(LinkList)malloc(sizeof(Node));
     end=(LinkList)malloc(sizeof(Node));//特别注意,申请空间要放到InitList函数前,如果将空间的申请放到InitList函数里执行就会出错 
     InitList(head,end);//链表初始化  
     Creat(end,5);//创建五个结点,并将其连在结点上 
     puts("创建完成后,顺序输出:"); 
     Show(head);//正序输出 
     puts("创建完成后,逆序输出:"); 
     ReShow(end);//逆序输出 
     LinkList P,S;
     P=GetElem(head,2);
     S=(LinkList)malloc(sizeof(Node));
     S->date=10;//为了表示方便,在这里将S中的信息设为10 
     printf("P结点储存的信息为:%d\n",P->date);
     printf("S结点储存的信息为:%d\n",S->date);
     InsertBefore(P,S);
     puts("在P之前插入S(10),顺序输出:");
     Show(head);//正序输出 
     puts("在P之前插入S(10),逆序输出:");
     ReShow(end);//逆序输出
     P=GetElem(head,2);//此时P=10 
     S=(LinkList)malloc(sizeof(Node));
     S->date=11;//为了表示方便,在这里将S中的信息设为11 
     printf("P结点储存的信息为:%d\n",P->date);
     printf("S结点储存的信息为:%d\n",S->date);
     InsertAfter(P,S);
     puts("在P后插入S(11),顺序输出:");
     Show(head);//正序输出 
     puts("在P后插入S(11),逆序输出:");
     ReShow(end);//逆序输出
     printf("P结点储存的信息为:%d\n",P->date);
     DeletBefore(P);
     puts("删除P之前结点顺序输出:");
     Show(head);
     puts("删除P之前结点逆序输出:");
     ReShow(end);
     P=GetElem(head,2);//此时P=11 
     printf("P结点储存的信息为:%d\n",P->date);
     DeletAfter(P);
     puts("删除P之后的结点顺序输出:");
     Show(head);
     puts("删除P之后的结点逆序输出:");
     ReShow(end);
     P=GetElem(head,2);//此时P=11 
     printf("P结点储存的信息为:%d\n",P->date);
     DeletItself(P);
     puts("删除P结点顺序输出:");
     Show(head);
     puts("删除P结点逆序输出:");
     ReShow(end);
    }

    自然,程序需要有头文件#include<malloc.h>
    运行结果如下:
    在这里插入图片描述

    展开全文
  • 双向链表实现结点

    2018-04-11 08:47:19
    定义、实现并测试一个双向链表结点类DNode。...编写主程序:输入不少于3组x、y整数,分别利用左侧和右侧插入结点函数组织数据为双向链表,测试输出链表中每个结点的左侧和右侧相邻节点内容,测试对左右侧结点删除
  • 双向链表结点的插入和删除算法

    千次阅读 多人点赞 2018-10-03 23:47:46
    双向链表的插入与删除 双向链表结点定义 #define ElemType int //双向链表的存储结构 typedef struct DuLNode ...双向链表结点删除 ...画图表示,并在上述双向链表中一个已知结点p之后插入一个结...
  • 内存中一片连续空间(不妨假设地址从1到m),提供给两个栈S1和S2使用,怎样分配这部分存储空间,使得对任一个栈,仅当这部分空间全满时才发生上溢。
  • 5双链表带头结点

    2020-10-06 23:14:33
    //初始化、判空、在p结点之后插入s结点、删除p结点的后继结点、销毁双链表 //尾插法建立双链表、头插法建立双链表、输出 #include <stdio.h> #include <stdlib.h>//malloc,free函数库 typedef int ...
  • 是否是最近编写链表的程序写多了,今天写的这个《删除带头结点循环链表p中第i个结点》一次就成功,呵呵!值得小小的奖励下!不过,删除双向链表中的某个节点是较简单点,写出来与大家分享分享 #include#include...
  • 双向链表添加节点和删除结点

    千次阅读 2018-03-26 14:45:48
    以下是添加头节点的代码:void CList::AddHead(DATA data) { SNode*p = new SNode; p-&gt;data = data; if (m_pHead) ...//链表为空第一次添加节点时候才会执行这一步 } p-&gt;pPrev = nullp...
  • 在双向链表存储结构中,删除p所指的结点时需修改指针的操作为 p-&gt;next-&gt;prior=p-&gt;prior; p-&gt;prior-&gt;next=p-&gt;next; p-&gt;next=p-&gt;next-&gt;next;p-&...
  • #include<stdio.h> typedef struct DuLNode { int data; struct DuLNode *prior; struct DuLNode *next; }DuLNode,* DuLinkList; void ListDelete(DuLinkList &L,DuLNode *p,int &...
  • 在双向链表存储结构中,删除p所指的结点时须修改指针()【MOOC选择题】
  • 1、给定一个链表,查找链表的倒数第n个节点,若查找成功,...next,p1指向头节点head,当遍历到链表最后一个结点时,p所指向的结点即为所查找的结点 int deleteElem(LNode *head,int k){ p1=head->next; p=he...
  • 题目:给定一个链表删除链表的倒数第 n 个节点,并且返回链表的头结点(给定的 n 保证是有效的,你能尝试使用一趟扫描实现吗?) 思想:采取双重遍历肯定是可以解决问题的,但题目要求我们一次遍历解决问题,那...
  • 双链表

    2020-09-29 22:03:45
    双链表在单链表的结点中增加了一个指向其前驱的prior指针; 这句理解为:让s结点指向和p结点相同的位置,注意是让s指向p指的位置! 判断p结点是否有后继结点,* 如果有*则p结点的后继结点的前项指针...删除p结点.

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 178
精华内容 71
关键字:

双链表删除p结点