在O(1)的时间内删除链表的一个节点

来源:互联网 发布:海洋电影源码 编辑:程序博客网 时间:2024/06/06 04:24

#include<iostream>
#include<math.h>
using namespace std;

struct ListNode
{
 int nValue;
 struct ListNode *pNext;
};

//如果这个函数参数传递的是一个指针,则函数会定义个指针pp指向实参所指向的地址,即和p指向同一个内存
//函数内部对指针pp内容的改变,同时会影响到p的内容,因为两个指针指向同一个内存。但是如果把pp指向其他的
//内存,即对pp进行重新赋值,然后对pp的内容的改变,不会影响到p的内容,因为此时两个指针指向不同的内存了
//所以要想改变指针pp的指向的情况下,对指针pp的改变同时影响到p的内容,可以参数传递指针的指针,即p的地址,这样
//在函数内,通过*pp = q; q是一个新的指针,指向不同的地址。
//ListNode* CreateList(ListNode* pp)
ListNode* CreateList(ListNode** pp)
{
 int a;
 ListNode *pHead = NULL;
 ListNode *pCur = NULL;

 int i = 1;
 while(cin>>a && a)
 {
  ListNode *p = new ListNode;
  p->nValue = a;
  p->pNext = NULL;
  
  if(i++ == 6)
   *pp = p;
  /*p->pNext = pHead;
  pHead = p;*/
  //----------------------------------------
  if(pCur == NULL)
  {
   pHead = p;
   pCur = p;
  }
  else
  {
   pCur->pNext = p;
   pCur = p;
  }
  //----------------------------------------
 }
 return pHead;
}
//删除p指针指向的节点
ListNode* DeletePNode(ListNode* pHead, ListNode* p)
{
 //如果pHead或p为NULL直接返回pHead
 if(pHead == NULL || p == NULL)
  return pHead;
 //如果要删除的是最后一个节点,则必须要从头遍历到倒数第二个节点,因为如法直接把最后一个节点赋值为NULL
 if(p->pNext == NULL)
 {
  //如果只有一个头结点,则直接返回NULL
  if(pHead == p)
   return NULL;
  else
  {
   //否则从头遍历到倒数第二个节点,然后删除最后一个节点
   ListNode* q = pHead;
   while(q->pNext != p)
    q = q->pNext;
   q->pNext = NULL;
  }
 }
 else
 {
  //如果删除的不是最后一个节点,则把要删除的节点的后一个节点的nValue值和pNext指针赋给要删除的节点
  //即把后一个节点的内容赋给删除节点,然后删除后一个节点,即是间接删除了要删除节点,实质上是删除了后一个节点
  ListNode* temp = p->pNext;
  p->nValue = temp->nValue;
  p->pNext = temp->pNext;
  delete temp;
  temp = NULL;
 }

 return pHead;
}

int main(int argc,char* argv[])
{
 //ListNode* p只是申明了一个指针,没有定义,所以没有分配内存空间,不能作为参数传递CreateList(p),
 //只能new一个对象给它才是定义,分配内存空间,即指针指向一个地址
 ListNode* p = new ListNode;

 //ListNode* pHead = CreateList(p);
 ListNode* pHead = CreateList(&p);
 pHead = DeletePNode(pHead,p);

 system("pause");
 return 0;
}