带头结点的链表和声明指向第一个元素的头指针

严蔚敏老师的数据结构分析一书中,都是采用带头结点的链表,可能读者一时间还不知道是什么意思:首先看一段伪代码:

L是链表的头结点

L=(LinkList)malloc(sizeof(LNode));

L->next=NULL;

链表的头指针也是一个结点,尽管这是一个空的结点,只是说明这个结点并没有携带任何有效的参数。

而我的实现当中确实没有分配一个结点,而只是一个指针,指向第一个元素。

typedef struct SNode{
    int nData;
    SNode* pNextNode;
}SNode,pSNode;

class CList
{
private:
    SNode* m_pListHeader;
    SNode* m_pListTail;
public:
    CList();
    ~CList();
    void InsertList(int a);
    void Merge(CList* p1,CList *p2);
    void Display();

};
void CList::InsertList(int a){
    SNode* pNewNode=new SNode;
    pNewNode->nData=a;
    pNewNode->pNextNode=NULL;
    if(NULL==m_pListHeader)
    {
        m_pListHeader=m_pListTail=pNewNode;
    }
    else
    {
        m_pListTail->pNextNode=pNewNode;
        m_pListTail=pNewNode;
    }
}

从插入结点就可以了解到我并没有申请头结点,而是将一个元素的指针赋值给了头指针。

两种方法有什么不同的地方,对于操作者来说应该如何区分:

这i里涉及到我们对查询的当前结点不感兴趣,而只是对当前结点的前一个结点感兴趣的时候,问题来了,主要是删除结点的时候会比较麻烦:

 int  CStudentLink::DelStudentNode(int id){
    //链表为空,返回
    if(NULL==m_pStudentLinkHeader)
    {
        return -1;
    }

    //尝试查询第一个元素
    if(id==m_pStudentLinkHeader->nID)
    {
        cout<<"delete ID:"<<m_pStudentLinkHeader->nID<<endl;
        delete m_pStudentLinkHeader;
        m_pStudentLinkHeader=m_pStudentLinkHeader->pNextNode;
        //m_pStudentLinkHeader==NULL;ERROR:后面可能还有元素
        return 0;
    }

    //如果下一个节点为空,返回
    if(NULL==m_pStudentLinkHeader->pNextNode)
    {
        return -2;
    }

    //如果第二个元素不为空,遍历第二元素
    SStudentNode* pTmpNode=m_pStudentLinkHeader;
    SStudentNode* pNextTmp=pTmpNode->pNextNode;
    while(NULL!=pNextTmp)
    {
        if(id==pNextTmp->nID)
        {
                pTmpNode->pNextNode=pNextTmp->pNextNode;
                cout<<"delete ID:"<<pNextTmp->nID<<endl;
                delete pNextTmp;
                pNextTmp=NULL;
                return 0;
        }
        pTmpNode=pNextTmp;
        pNextTmp=pNextTmp->pNextNode;
    }
    cout<<"Travser all node ,but not match"<<endl;
    return -3;
}

为了实现学生结点的删除,上面的代码不少了,如果我们是使用创建一个空的头结点的方式,应该会非常的轻松。

    SNode* pTmp=m_pStudentLinkHeader;   
    while(NULL!=pTmp->pNextNode)
    {
       if(id==pTmp->pNextNode->nID)
       {
           SNode* p=pTmp->pNextNode;
           pTmp->pNextNode=pTmp->pNextNode->pNextNode;
           delete p;
           return 0;
       }
       pTmp=pTmp->pNextNode;
    }
    return -1;
时间: 2024-10-23 07:07:24

带头结点的链表和声明指向第一个元素的头指针的相关文章

不带头结点的链表的增删改查

这两天都在学习数据结构中的链表操作,觉得有很多东西想跟大家分享,通常写链表一般会创建一个带头结点的链表,带头结点链表非常容易的进行链表的遍历,而不带头结点的链表,一马虎就会指错,所以在这里跟大家分享下我进行没有头结点的创建时的心得! 1.创建无头结点链表(头插) 2.删除中间节点(不是第一个也不是最后一个) 1 #include<stdio.h> 2 #include<malloc.h> 3 typedef char ElemType; 4 typedef struct node

链表习题(3)-将带头结点的链表进行逆置

1 /*将带头结点的链表进行逆置*/ 2 /* 3 算法思想:设逆置链表尾空,将原链表中的结点依次删除后,按头插法插入逆置链表中,直至 4 原链表为空 5 */ 6 void Reverse(LinkList& L) 7 { 8 LNode *p, *q; 9 p = L->next; 10 L->next = NULL; 11 while (p) 12 { 13 q = p; 14 p = p->next; 15 /*头插法*/ 16 q->next = L->ne

数据结构笔记5带头结点单链表

/* 本次操作是对带头节点单链表的操作  包括删除  插入 判空 建立  包括删除插入函数  显示函数 目的是为了对单链表做一个基本操作的总结----1*/ #include<stdio.h>#include<malloc.h>#include<conio.h>#define OK 1#define ERROR -1#define OVERFLOW -2#define ENDFLAG 0typedef struct LNode{ int data; struct LNo

数据结构-1 带头结点的链表合并

List Merge( List L1, List L2 ){ struct Node *h,*p,*l1,*l2; h = (struct Node*)malloc(sizeof(struct Node)); h->Next = NULL; p = h; l1 = L1->Next; l2 = L2->Next; while(l1!=NULL && l2!=NULL){ if(l1->Data > l2->Data){ p->Next = l2;

带头结点的链表

#include<stdio.h> #include<stdlib.h> #define N 9 typedef struct node{ int  data; struct node * next; }ElemSN; ElemSN  * Createlink(int a[],int n){ int i; ElemSN * h, * p; h=p=(ElemSN *)malloc(sizeof(ElemSN)); h->next=NULL; for( i=0;i<N;i

2.8~2.12带头节点的链表的基本操作

2.8和2.9在带头结点的链表中实现插入和获取元素的操作 #include<stdio.h> #include<stdlib.h> #include<math.h> typedef int Status ; typedef int ElemType; #define OK 1 #define ERROR 0 typedef struct LNode { ElemType data; struct LNode *next; }LNode,*LinkList; Status

链表不带头结点的实现

首先要强调的是,ADT没有变化,只是实现上的变化. 不带头结点的实现比带头结点的实现稍微复杂一些,尤其体现在插入(第58-60行)和删除(第88-91行),要单独处理表头改变的情况.而带头结点的链表表头不会变化,总是指向头结点. 其他操作的不同之处同学们自行比较. 下面的问题会帮助你的理解: 第83行 while(p && j < i - 1) {   而教材上带头结点的实现为while(p->next && j < i - 1) { 为什么会有这种区别?

C语言实现单链表的节点插入(带头结点)

我在之前一篇博客<C语言实现单链表(不带头结点)节点的插入>中具体实现了怎样在一个不带头结点的单链表中进行节点的插入.可是在实际应用中,带头结点的链表更为经常使用.更为方便.今天我们就要来使用带头结点的单链表进行节点的插入.演示样例代码上传至 https://github.com/chenyufeng1991/InsertList_HeadNode  . 核心代码例如以下: Node *InsertNode(Node *pNode,int pos,int x){ int i = 0; Node

C语言实现单链表(带头结点)的基本操作

我在之前一篇博客<C语言实现单链表(不带头结点)的基本操作>中具体实现了不带头结点的单链表的11种操作:如计算链表长度.初始化.创建链表.清空链表等等.但是在实际使用中,带头结点的单链表往往比不带头结点的单链表用的更多,使用也更为方便.因为不用单独考虑第一个节点的情况了,第一个节点和其他后续节点的处理全都一样了,简化操作.这篇博客将会来实现带头结点的单链表的11种操作.代码上传至: https://github.com/chenyufeng1991/LinkedList_HeadNode  .