线性表的顺序存储实现(二)单链表、双链表、循环链表

单链表

带头结点

初始化

// 带头结点的单链表

bool InitList_head(LinkList &L)
{
    L = (LNode *)malloc(sizeof(LNode)); // 分配一个头节点
    if (L == NULL)
    {
        return false; // 内存不足,分配失败
    }
    L->next = NULL; // 头结点之后还没节点
    return true;
}

空链判断

bool Empty_head(LinkList L)
{
    if (L->next == NULL) // 只有一个头结点的 “带头结点的单链表” => 空表
    {
        return true;
    }
    else
    {
        return false;
    }
}

按位序插入

bool ListInsert(LinkList &L, int i, int e) // 按位序插入
{
    if (i < 1)
    {
        return false;
    }
    LNode *p;  // 指针p指向当前扫描到的节点
    int j = 0; // 当前p指向的是第几个节点
    p = L;
    while (p != NULL && j < i - 1) // 遍历链表找到第i-1个节点
    {
        p = p->next;
        j++;
    }
    if (p == NULL) // i值不合法 插到无前驱也无后继的位置
    {
        return false;
    }

    LNode *s = (LNode *)malloc(sizeof(LNode)); // 申请一个新的节点空间
    s->data = e;
    s->next = p->next; // s 指向第i个元素
    
    p->next = s; // 第i-1个元素指向 s

    return true;
}

某结点前插入

bool InsertPrioNode(LNode *p, int e) // 在指定节p点前插入元素 e  // 思路:先插到p之后,再交换p存的值p->data与新节点存的值e
{
    if( p==NULL )
    {
        return false;
    }
    LNode *s = (LNode *)malloc(sizeof( LNode ));
    if( s==NULL )
    {
        return false;
    }
    s->next = p->next;  // s 插入到 p 后面
    p->next = s;
    s->data = p->data;  // p s 互换data
    p->data = e;

    return true;
    
}

某结点后插入

bool InsertNextNode(LNode *p, int e) // 在指定节点p后插入元素 e
{
    if(p == NULL)
    {
        return false;
    }
    LNode *s = (LNode *)malloc(sizeof(LNode));
    if(s == NULL) // 内存分配失败
    {
        return false;
    }
    s->data = e;
    s->next = p->next; // s 指向 p的下一个节点
    p->next = s; // p 指向 s

    return true;
}

按位序删

bool ListDelete(LinkList &L, int i, int &e)  // 按位序删除
{
    if( i<1 )
    {
        return false;
    }
    LNode *p;  // 指向当前扫描到的节点
    int j = 0;  // 当前节点位序

    p = L;
    while( p!=NULL && j<i-1 )  // 循环到 j = i-1;
    {
        p = p->next;
        j++;
    }
    if( p==NULL )  // 位置 i 不合法
    {
        return false;
    }
    if( p->next == NULL )  // 不存在第 i 位元素
    {
        return false;
    }
    LNode *q = p->next;
    e = q->data;
    p->next = q->next;

    free(q);
    return true;

}

删除指定结点

bool DeleteNode(LNode *p)  // 删除指定节点  // 思路:*p 与其后继 q 互换值, 删掉后继节点 q, 但
{
    if( p==NULL )
    {
        return false;
    }
    LNode *q = p->next;  // q 指向 *p 的后继节点  
    
    p->data = p->next->data;
    p->next = q->next;  // 将 q 节点从链中断开
    free(q);

    return true;

}

按位序查找

LNode * GetElem(LinkList &L, int i) // 按位查找 返回第i位元素
{
    if (i < 1)
    {
        return NULL;
    }
    LNode *p;  // 指针p指向当前扫描到的节点
    int j=0;   // 当前p指向的是第几个节点
    p = L;
    while (p != NULL && j < i) // 遍历链表找到第 i 个节点
    {
        p = p->next;
        j++;
    }
    // if (p == NULL) // i值不合法 -> p退出时正好时 NULL
    // {
    //     return NULL;
    // }

    return p;
}

按值查找

LNode * LocateElem( LinkList L, int e )  // 按值查找
{
    LNode *p = L->next;  // 从第 1 个元素开始查找
    while( p != NULL && p->data != e)  // 循环到值为e的节点 p
    {
        p = p->next;
    }
    
    return p;
}

链表长度

int Length(LinkList L)
{
    int len = 0;  // 统计表长
    LNode *p = L;
    while( p->next != NULL )
    {
        p = p->next;
        len++;
    }

    return len;
}

打印链表

void PrintLink( LinkList L )
{
    printf("Length: %i \n", Length(L));

    LNode *p;
    int t=0; // 记录位序
    p = L->next;  // 从头结点之后开始打印

    printf("HeadNode ->");
    while( p != NULL )
    {
        t++;
        printf(" %i -> ", p->data);
        p = p->next;
    }
    puts(" NULL\n");
}

主函数(用于测试)

int main()
{
    // 创建单链表
    LinkList L;
    InitList_head(L);
    PrintLink(L);


    // 按位序插入
    for(int i=0; i<5; i++)
    {
        ListInsert(L, i+1, i+1); 
    }
    PrintLink(L);
    // 在某节点后插入
    LNode *np;
    np = L->next;
    InsertNextNode(np, 100);
    printf("insert next node successful... node->data: %i\n", np->next->data);
    PrintLink(L);
    // 在某节点前插入
    LNode *pp;
    pp = L->next;
    InsertPrioNode(pp, 100);
    printf("insert prio node successful... node->data: %i\n", pp->next->data);
    PrintLink(L);

    // 按位序删除
    int e;
    ListDelete(L, 3, e);
    printf("del NO.3 %i successful...\n", e);
    PrintLink(L);
    // 删指定节点
    LNode *dp;
    dp = L->next;
    DeleteNode(dp);
    printf("del node  successful... NOW node->data=%i \n", dp->data);
    PrintLink(L);



    // 按位序查找
    LNode *p;
    p = GetElem(L, 3);
    printf("GetElem NO.3 : %i\n", p->data);

    // 按值查找
    LNode *q;
    q = LocateElem(L, 4);
    printf("LocateElem 4 :  q->data = %i\n", q->data);


    return 0;


    
}

测试结果

image

不带头结点

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JFLEARN

CSDN这么拉会有人打赏?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值