线性表链式结构基本操作(不带头结点的单链表)

不带头结点的单链表如图所示:

 1、初始化链表//将头指针置空,对头指针进行操作,所以参数为引用

void InitList(LinkList &slink)
{
    slink = NULL;
}

2、销毁链表//将malloc的空间全free掉,将头指针置空,所以参数是引用

void Destroy(LinkList &slink)
{
    /*
        遍历表,逐个free当前链表,直至表尾
        1、需要变量指向当前变量p
        2、需要变量保存当前变量的next
        2、循环条件当前变量是否为空
    */
    LinkList p= slink,q;
    while(p)
    {
        q= p->next;
        free(p);
        p = q;
    }
    slink = NULL;
}

 以上过程还可以简化如下:

用链表的头指针始终指向当前结点,这样就可以少定义一个变量(这区别于带头结点的链表)

void Destroy(LinkList &slink)
{
    /*
        遍历表,逐个free当前链表,直至表尾
        1、需要变量指向当前变量
        2、需要变量保存当前变量的next
        2、循环条件当前变量是否为空
    */
    LinkList q;
    while(slink)
    {
        q= slink->next;
        free(slink);
        slink = q;
    }
    //slink = NULL;
}

 小结:while循环条件中变量的值,跳出循环后,最终是等于不满足循环条件的那个值。

 或者用变量q先保存住头指针,然后,头指针指向他的next,最后,释放掉q

void destroyList(LinkList &slink)
{
    /*
        遍历表,逐个free当前链表,直至表尾
        1、需要变量指向当前变量
        2、需要变量保存当前变量的next
        2、循环条件当前变量是否为空
    */
    LinkList q;
    while(slink)
    {
        q= slink;
        slink = slink->next;
        free(q);
        
    }
    //slink = NULL;
}

3、将链表数据清空

//与销毁表完全相同

#define clearList  destroyList

给destroyList 起个新名字叫clearList

4、求链表的长度

int LengthList(LinkList L)
{
    int i=0;        //计数变量
    LinkList p =L;  //指向当前结点的变量
    while(p)
    {
        i++;
        p = p->next;
    }
    return i;
}

5、链表中插入元素

寻找i-1的位置,可以包含住在链尾插入元素的情况。

插入元素前,一定要先保存好i-1的next指针,因为,这个会被改变,而改变了的话,就无法找到i结点了。

不带头结点的链表,插入结点操作时,需要传引用,因为如果在表头插入的话,会改变链表。

方法一:

bool insertList(LinkList &slink,int e,int i)
{
    /*
        思路:寻找i-1的位置,因为找到i-1就能找到i及i+1的位置
        i的范围是1-最后一个结点+1
        1、计数变量j
        2、当前结点变量
        3、临时变量用来malloc
        4、循环条件,
        
    */
    if(i<1) return false;
    int j=1;
    LinkList p = slink;
    LinkList q = (LinkList)malloc(sizeof(Node));
    q->data = e;

    if(i==1)
    {   
        q->next = p;
        slink = q;//此处得用slink,因为链表改变了。
        return true;
        
    }    
    while(p&&j<i-1)//j=1,代入,i>2,未包含i=1的情况
    {
        p = p->next;
        j++;
    }
    if(p)
    {
        q->next = p->next;
        p->next = q;  
        return true;      
    }    
    return false;
}

 方法二:

bool insertList(LinkList &slink,int e,int i)
{
    /*
        思路:寻找i-1的位置,因为找到i-1就能找到i及i+1的位置
        i的范围是1-最后一个结点+1
        1、计数变量j
        2、当前结点变量
        3、临时变量用来malloc
        4、循环条件,
        
    */
    if(i<1) return false;
    int j=1;
    LinkList p = slink;
    LinkList q = (LinkList)malloc(sizeof(Node));
    q->data = e;

    if(i==1)
    {   
        q->next = slink;
        slink = q;//此处得用slink,因为链表改变了。
        return true;
        
    }    
    while(p&&j<i-1)//j=1,代入,i>2,未包含i=1的情况
    {
        p = p->next;
        j++;
    }
    if(!p) 
    return false;
    q->next = p->next;
    p->next = q;  
    return true; 
}

 注意:程序中,只用了if(!p).....,是因为前面已经判断了i<1的情况了。

6、链表中删除数据

bool deleteList(LinkList &slink,int i)
{
    /*
        缩小i的范围:i的值从1-表尾
        找第i-1个结点
        1、变量计数
        2、变量指向当前结点
        3、循环条件:当前结点不为空,计数小于i-1        
    */
    int j=1;
    LinkList p = slink;
    LinkList temp ;
    if(i==1)
    {
        slink = slink->next;
        free(p);      
        return true;
    }
    while(p&&j<i-1);//代入j=1,i>2,故未包含i=1的情况
    {
        P = P->next;
        j++;
    }
    if(!p||j>i-1)
    return false;
    temp = p->next;
    p->next = temp->next;
    free(temp);
    return true;
    
}

 

注意:与删除结点的方法二进行比较会发现,此处多了j>i-1,少了if(i<0) return false;的情况,

代数检查可以验证,加上j>i-1条件,可以排除掉i<0的情况。

7、链表中返回元素的直接前驱

注意:找前驱的话,循环条件要判断当前值的后继是否为空,如果判断当前值的话,就无法找到前驱了。

方法一:正向思维

void priorList(LinkList slink,int value,int &e)
{
    /*
        该值的范围:
        从第一个结点的后继开始,判断到倒数第二个结点的后继
        1、变量指向当前结点
    
    */
    LinkList p = slink;
    LinkList q;
    while(p->next)
    {
        q = p->next;
        if(q->data==value)
        {
            e = p->data;
            return true;
        }
        p = q;
    }
     return false;
}

 方法二:逆向思维

void priorList(LinkList slink,int value,int &e)
{
    /*
        该值的范围:
        从第一个结点的后继开始,判断到倒数第二个结点的后继
        1、变量指向当前结点
    
    */
    LinkList p = slink;
    LinkList q;
    while(p->next&&p->next->data!=value)
    {
        p = p->next;       
    }
    if(p->next)
    {
        e = p->next->data;
        return true;
    }
     return false;
}

8、返回与链表中某值相等元素的直接后继

方法一:正向思维

void nextList(LinkList slink,int value,int &e)
{
    /*
        1、指向当前结点的变量
        3、循环条件:当前结点的后继结点不为空
        此次,我们次用正向思维方式,while循环中找到该值返回
     */
        LinkList p = slink;
        while(p->next)
        {
            if(p->data == value)
              {
                    e = p->next->data;
                    return true; 
               }
             p = p->next;
        }
        return false;
}

方法二: 逆向思维

void nextList(LinkList slink,int value,int &e)
{
        LinkList p = slink;
        while(!p->next&&p->data != value)
        {           
             p = p->next;
        }
        if(!p->next)
        {
              e = p->next->data;
              return true; 
        }
        return false;
}

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值