数据结构 单链表

typedef struct LNode
{
    //单链表的存储结构
    Elemtype data;
    struct LNode *next;
} LNode,*LinkList;
//LinkList为指向结构体LNode的指针类型

为了提高程序的可读性,在此对同一结构体指针类型起了两个名称,LinkList 与 LNode*, 两者本质上是等价的。

通常习惯上用LinkList定义单链表,强调定义的是某个单链表的头指针;用LNode*定义指向单链表中任意结点的指针变量。例如,若定义LinkList L,则L为单链表的头指针,若定义LNode *p, 则p为指向单链表中某个结点的指针,用*p代表 该结点。当然也可以使用定义LinkList p, 这种定义形式完全等价于LNode*p。 

关于首元节点、头节点、头指针。

首元结点是指链表中存储第一个数据元素a1 的结点。

头结点是在首元结点之前附设的一个结点,其指针域指向首元结点。头结点的数据域可以不存储任何信息,也可存储与数据元素类型相同的其他附加信息。例如,当数据元素为整数型时,头结点的数据域中可存放该线性表的长度。

头指针是指向链表中第一个结点的指针。若链表设有头结点,则头指针所 指结点为线性表的头结点;若链表不设头结点,则头指针所指结点为该线性表的首元结点。 

第一个阴影节点为头节点,ZHAO节点为首元节点,L为头指针。

typedef struct LNode
{
    //单链表的存储结构
    Elemtype data;
    struct LNode *next;
} LNode,*LinkList;
//LinkList为指向结构体LNode的指针类型

bool InitList(LinkList &L)
{
    //构造一个空的单链表L
    L=new LNode;//生成新节点作为头节点,用头指针L指向头节点
    L->next=NULL;
    return true;
}

bool GetElem(LinkList L,int i,Elemtype &e)
{

    //在带头节点的单链表L中根据序号i获取元素的值,
    //用e返回第i个数据元素的值,i的值从1开始
    LNode* p = L->next;
    int cnt = 1;
    while(p&&cnt<i)
    {
        p=p->next;
        cnt++;
    }
    if(!p || cnt>i)//i<=0或者i>L的长度
        return false;
    e=p->data;
    return true;
}

LNode* LocateElem(LinkList L,Elemtype e)
{
    //在带头节点的单链表L中查找值为e的元素
    LNode* p=L->next;
    while(p && p->data!=e)
    {
        p=p->next;
    }
    //查找失败p为NULL
    return p;
}

bool ListInsert(LinkList &L,int i,Elemtype e)
{
    //插入节点,L为带头节点的单链表
    LNode* p1=L;
    int cnt=0;
    while(cnt<i-1 && p1)
    {
        p1=p1->next;
        cnt++;
    }
    if(!p1 || cnt>i-1)
    {
        return false;
    }

    LNode* t = new LNode();
    t->data=e;
    t->next=p1->next;
    p1->next=t;
    return true;
}

bool ListDelete(LinkList &L,int i)
{
    /*
    删除算法中的循环条件(p->next&&cnt<i-1)和
    插入算法中的循环条件(p&&(cnt<i—1))是有所区别的。
    因为插入操作中合法的插入位置有n+l个,而删除操作中
    合法的删除位置只有n 个,
    如果使用与插入操作相同的循环条件,
    则会出现引用空指针的情况,使删除操作失败。
    */
    //删除链表L中第i个节点
    LNode *p=L;
    int cnt=0;
    while(cnt<i-1 && p->next)
    {
        p=p->next;
        cnt++;
    }
    if(!(p->next) || cnt>i-1)
        return false;
    LNode* q=p->next;
    p->next=q->next;
    delete q;
    return true;
}

void CreateList_H(LinkList &L,int n)
{
    //前插法
    //逆位序输入n个元素的值,建立带表头结点的单链表L
    L=new LNode;
    L->next=NULL;
    for(int i=0; i<n; i++)
    {
        LNode* p=new LNode();
        cin>>p->data;
        p->next=L->next;
        L->next=p;
    }
}

void CreateList_R(LinkList &L,int n)
{
    //后插法
    //正位序输人n个元素的值,建立带表头结点的单链表L
    L=new LNode();
    LNode* r=L;
    for(int i=0; i<n; i++)
    {
        LNode* q=new LNode();
        cin>>q->data;
        q->next=r->next;
        r->next=q;
        r=q;
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值