通过与 Jira 对比,让您更全面了解 PingCode

  • 首页
  • 需求与产品管理
  • 项目管理
  • 测试与缺陷管理
  • 知识管理
  • 效能度量
        • 更多产品

          客户为中心的产品管理工具

          专业的软件研发项目管理工具

          简单易用的团队知识库管理

          可量化的研发效能度量工具

          测试用例维护与计划执行

          以团队为中心的协作沟通

          研发工作流自动化工具

          账号认证与安全管理工具

          Why PingCode
          为什么选择 PingCode ?

          6000+企业信赖之选,为研发团队降本增效

        • 行业解决方案
          先进制造(即将上线)
        • 解决方案1
        • 解决方案2
  • Jira替代方案

25人以下免费

目录

链表的基本操作是什么

链表的基本操作包括初始化。通常会用头指针来标识一个单链表,头指针为NULL时表示一个空表。但是,为了操作方便,会在单链表的名列前茅个结点之前附加一个结点,称为头结点。

一、链表的基本操作

初始化

通常会用头指针来标识一个单链表,头指针为NULL时表示一个空表。但是,为了操作方便,会在单链表的名列前茅个结点之前附加一个结点,称为头结点。头结点的数据域可以不设任何信息,也可以记录表长等信息。头结点的指针域指向线性表的名列前茅个元素结点。如下图所示:

头结点和头指针的区分:不管带不带头结点,头指针始终指向单链表的名列前茅个结点,而头结点是带头结点的单链表中的名列前茅个结点,结点内通常不存储信息。

 那么单链表的初始化操作就是申请一个头结点,将指针域置空。

void InitList(LinkList &L){

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

    L->next = NULL;

}

建立单链表

头插法建立单链表

所谓头插法建立单链表是说将新结点插入到当前链表的表头,即头结点之后。:

算法思想:首先初始化一个单链表,其头结点为空,然后循环插入新结点*s:将s的next指向头结点的下一个结点,然后将头结点的next指向s。

实现代码:

//头插法建立单链表

LinkList HeadInsert(LinkList &L){

    InitList(L); //初始化

    int x;

    cin>>x;

    while(x!=9999){ //输入9999表示结束

        LNode *s = (LNode *)malloc(sizeof(LNode));

        s->data = x;

        s->next = L->next;

        L->next = s;

        cin>>x;

    }

    return L;

}

需要指出的是,头插法建立的单链表中结点的次序和输入数据的顺序不一致,是相反的。若希望两者的顺序是一致的,则可采用尾插法建立单链表。

尾插法建立单链表

所谓尾插法建立单链表,就是将新结点插入到当前链表的表尾。如下图所示:

算法思想:首先初始化一个单链表,然后声明一个尾指针r,让r始终指向当前链表的尾结点,循环向单链表的尾部插入新的结点*s,将尾指针r的next域指向新结点,再修改尾指针r指向新结点,也就是当前链表的尾结点。最后别忘记将尾结点的指针域置空。

 实现代码:

//尾插法建立单链表

LinkList TailInsert(LinkList &L){

    InitList(L);

    LNode *s,*r=L;

    int x;

    cin>>x;

    while(x!=9999){

        s = (LNode *)malloc(sizeof(LNode));

        s->data = x;

        r->next = s;

        r = s;

        cin>>x;

    }

    r->next = NULL;

    return L;

}

遍历单链表

算法思想:声明一个指针p,从头结点指向的名列前茅个结点开始,如果p不为空,那么就输出当前结点的值,并将p指向下一个结点,直到遍历到最后一个结点为止。

实现代码:

//遍历操作

void PrintList(LinkList L){

    LNode *p = L->next;

    while(p){

        cout<<p->data<<” “;

        p = p->next;

    }

    cout<<endl;

}

求单链表的长度

算法思想:声明一个指针p,p指向头结点指向的名列前茅个结点,如果p指向的结点不为空,那么长度加一,将p指向下一个结点,直到遍历到最后一个结点为止。

实现代码:

//求单链表的长度

int Length(LinkList L){

    LNode *p = L->next;

    int len = 0;

    while(p){

        len++;

        p = p->next;

    }

    return len;

}

延伸阅读:

二、线性表基本架构

对于一个线性表来说。不管它的具体实现如何,但是它们的方法函数名和实现效果应该一致(即使用方法相同、达成逻辑上效果相同,差别的是运行效率)。线性表的概念与Java的接口/抽象类有那么几分相似。非常知名的就是List的Arraylist和LinkedList,List是一种逻辑上的结构,表示这种结构为线性表,而ArrayList,LinkedList更多的是一种物理结构(数组和链表)。

所以基于面向对象的编程思维,我们可以将线性表写成一个接口,而具体实现的顺序表和链表的类可以实现这个线性表的方法,提高程序的可读性,还有一点比较重要的,记得初学数据结构与算法时候实现的线性表都是固定类型(int),随着知识的进步,我们应当采用泛型来实现更合理。至于接口的具体设计如下:

package LinerList;

public interface ListInterface<T> {   

    void Init(int initsize);//初始化表

    int length();

    boolean isEmpty();//是否为空

    int ElemIndex(T t);//找到编号

    T getElem(int index) throws Exception;//根据index获取数据

    void add(int index,T t) throws Exception;//根据index插入数据

    void delete(int index) throws Exception;

    void add(T t) throws Exception;//尾部插入

    void set(int index,T t) throws Exception;

    String toString();//转成String输出   

}

相关文章