线性链表1

2.3.1线性链表

单链表,用一个指针表示逻辑关系。

特点:每个数据元素由节点(Node)构成。

|data|next|

线性结构

head->a1|->a2|->a3|^

节点可以连续也可以不连续。

首节点:

链表中第一个元素节点成为首节点

尾节点:

链表中最后一个元素,指针域为空。

单链表分为带头结点和不带头结点两种类型。有头节点可以简化运算的实现过程。

空链表的标志就是头节点的指针域为空。

代码cpp

#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef int Status;
#define OK 1
#define ERROR 0

//-------------------结点的c语言描述
typedef struct node
{
    ElemType data;     // 数据
    struct node *next; // 后继结点指针。指针类型是node,去掉指针后会有语法错误,因为是递归定义

} LNode, *LinkList; // LinkList是结构体指针
Status InitList(LinkList &L);
Status DestroyList(LinkList &L);
int ListLength(LinkList L);
int LocateElem(LinkList L, ElemType e);
Status LintInsert_L(LinkList &L, int i, ElemType e);
Status ListDelete_L(LinkList &L, int i, ElemType &e);
void Dis_List(LinkList &L);

int main()
{

    LinkList L;
    InitList(L);
    printf("刚初始化的链表长度:%d\n", ListLength(L));
    LintInsert_L(L, 1, 6);
    printf("插入一个元素以后的链表长度:%d\n", ListLength(L));
    Dis_List(L);
    LintInsert_L(L, 2, 66);
    Dis_List(L);
    LintInsert_L(L, 3, 666);
    Dis_List(L);
    int e;
    ListDelete_L(L,1,e);   //删除第i个元素并返回给e
    printf("删除第1个元素后:\n");
    Dis_List(L);
    printf("删除的值是:e=%d\n",e);

    printf("删除后长度:%d\n",ListLength(L));
    printf("元素666在列表中的位序:%d",LocateElem(L,666));    //查找指定元素在列表中的下标
    DestroyList(L);//销毁线性表
    //printf("销毁后长度:%d\n",ListLength(L));  //销毁后无法查看线性表的长度,会报错

}

// (1)
// 初始化单链表算法
// 创建一个空的单链表,他只有一个头结点,由L指向他。该
// 节点的next域为空,data域未设定任何值。
Status InitList(LinkList &L)
{ // 操作结果:构造一个空的线性表
    // 产生头节点,并使L指向此头节点
    L = (LinkList)malloc(sizeof(LNode));
    if (!L) // 空间分配失败
        return ERROR;
    L->next = NULL; // 指针域为空
    return OK;
}

// (2)销毁单链表
// 一个单链表中所有的结点空间都是malloc函数分配的,在不需要的时候要通过free函数释放所有的节点空间
// 小心后继节点消失
Status DestroyList(LinkList &L)
{
    // 初始条件:线性表L已存在。操作结果:销毁线性表L
    LinkList p; // 定义一个结构体指针p
    while (L)
    {                // 当L不为空的时候
        p = L->next; // p指向首元结点
        free(L);     // 释放L
        L = p;       // 将p给L
    }
    return OK;
}

// (3)求单链表长度算法,需要扫描一遍单链表
// 设置一个计数器,i=0,p初始指向第一个数据节点。然后沿next域逐个往后查找,每次移动一次
// i值增加,当p所指结点为空时,结束这个过程,i值就是表长
int ListLength(LinkList L)
{
    // 初始条件:线性表L已存在。操作结果;返回L中数据元素个数
    int i = 0;
    LinkList p = L->next; // 指向第一个结点
    while (p)
    { // 当p不空的时候,没有到表尾
        i++;
        p = p->next;
    }
    return i;
}

//(4)求单链表中值为e的元素的下标
// 用p从头开始遍历单链表L中的结点,用计数器i统计遍历过后
// 的节点,起初为0
// 在遍历时,若p不为空,则p所指结即为要找到的结点,
// 查找成功,算法返回位序i
// 否则算法返回0

int LocateElem(LinkList L, ElemType e)
{
    // 操作结果:返回L中第i个与e相等的数据元素的位序
    // 若这样的数据元素不存在,则返回0
    int i = 0;
    LinkList p = L->next; // 定义结构体指针p,指向第一个结点
    while (p)
    { // 如果第一个结点不存在也就是空,就不会进行下边的循环
      // 刚开始p是第一个结点然后p会向后移动,知道p为空
        i++;
        if (p->data == e)
        {
            return i; // 找到这样的数据元素
        }

        p = p->next;
    }
    return 0;
}

//(5)单链表的插入
// 在单链表L中第i个位置,插入值为x得结点
// 先在单链表L中查找第i-1个节点,若未找到返回0
// 找到后由p指向该节点,创建一个以x为值的新结点s,将其插入到p指结点之后。
Status LintInsert_L(LinkList &L, int i, ElemType e)
{
   // printf("e=%d\n", e);
    // 在带头结点的单链线性表L的第i个元素之前插入元素e
    LinkList p, s;
    p = L;
    int j = 0;
    while (p && j < i - 1)
    { // 找到i-1个结点 让p指向他
        p = p->next;
        ++j;
    }
    if (!p || j > i - 1)
    { // i<1或大于表长
        return ERROR;
    }
    s = (LinkList)malloc(sizeof(LNode)); // 生成新结点
    s->data = e;
    s->next = p->next; // 插入L中
    p->next = s;
    //printf("%d", (s->data));
    return OK;
}

//(6)单链表的删除操作
// 在单链表中删除第i个结点
// 先在单链表L中查找第i-1个节点,若未找到返回0
// 找到后由p指向该节点,然后让q指向后继节点(要删除的节点)
// 若q所指向结点为空则返回0,否则删除q结点并释放其占用空间
Status ListDelete_L(LinkList &L, int i, ElemType &e)
{
    // 在带头结点的单链表L中,删除第i个元素,并由e返回其值
    LinkList p, q;
    p = L;
    int j = 0;
    // 寻找第i个结点,并令p指向其前驱
    while (p->next && j < i - 1)
    {
        p = p->next;
        ++j;
    }

    if (!(p->next) || j > i - 1)
        return ERROR;  // 删除位置不合法
    q = p->next;       // 把要删除的元素给q
    p->next = q->next; // 要删除的元素的下一个节点给p的下一个结点,就是会将要删除的元素给隔过去
    e = q->data;       // 将要删除的数据赋值给e
    free(q);           // 释放要删除的元素
    return OK;
}

void Dis_List(LinkList &L)
{
    LinkList p;
    p = L->next;
    while (p)
    {
        printf("%d  ", p->data);
        p = p->next;
    }
    printf("\n");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

y6y6y666

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值