美文网首页算法笔记程序员今日看点
数据结构 线性表 链式存储结构

数据结构 线性表 链式存储结构

作者: SpiffyEight77 | 来源:发表于2017-01-26 20:52 被阅读111次
    Data Strucrure

    本文主要介绍线性表的链式存储结构

    为什么要使用链式存储结构?

    首先我们知道,根据线性表的顺序存储结构,我们可以对顺序表的数据元素进行随机存取,其存储位置可以用简单公式来表示。然而,顺序表在插入、删除操作上需要耗费大量时间在移动数据元素。另外数组长度相对固定的静态特性,导致当表中数据较多而其变化较大时,操作过程相对复杂,时间复杂度高,浪费时间。

    单链表定义与表示

    线性表的链式存储结构的特点是:用一组任意的存储单元存储线性表数据元素(这组存储单元可以连续,也可以不连续)。所以数据元素之间的逻辑关系除了存储自身数据之外,还需要存储一个指向其直接后继元素信息。所以链式表数据元素一般包含两个存储域,一个是存储自身数据的值域,另一个存储直接后继信息的指针域。

    Link.jpeg

    使用结构体定义单链表的结点

    typedef struct LNode
    {
      Elemtype data;
      struct LNode *next;
    }LNode,*LinkList;
    

    通常习惯上用LinkList定义单链表,强调定义的是某个单链表的头指针;用LNode*通常定义指向单链表中任意结点的指针变量。

    为什么要增加单链表头结点?

    首先头结点只包含指针域(即指向后继的地址),增加头结点是为了让首元结点拥有前驱结点,操作时无需对首元结点进行特殊处理。

    单链表基本操作与顺序表不同

    在顺序表中,两个相邻数据元素的物理位置是紧邻的,其存储位置可以通过简单公式得到,而在单链表中,数据元素的存储位置都是随机的。查找第i个数据元素时,只能从头指针的指针域L=L->next来查询,称为顺序存取。

    单链表基本操作

    1. 初始化单链表 InitLinkList(LinkList L)
    2. 单链表取直 GetElem(LinkList L,int i,ElemType e)
    3. 单链表查询 *LocateElem(LinkList L,ElemType e)
    4. 单链表插入 ListInsert(LinkList &L,int i,ElemType e)
    5. 单链表删除 ListDelete(LinkList &L,int i)
    6. 前插法创建单链表 CreateList_H(LinkList &L,int n)
    7. 后插法创建单链表 CreateList_R(LinkList &L,int n)

    基本操作分析

    1. 初始化单链表

    Status  InitList(LinklList &L)
    {
        L = new LNode;//new 一个新头结点
        L->next = NULL;//头结点的next域为NULL,代表为空链表
        return OK; 
    }//初始化
    

    2. 单链表取值(按值查找)

    Status GetElem(LinklList L,int i,int &e)
    {
        LinklList p;
        p = new LNode; //new 一个p结点
        p = L->next; //p结点为头结点指向的下一个结点
        if(i<=0) //判断是否在范围内
            return ERROR;
        for(int j=1;j<=i;j++)
        {
            p = p->next;
            if(!p) //p结点为空就返回ERROR
                return ERROR;
        }
        e = p->data; //否则e赋值为p结点的值域
        return OK;
    }//取值
    

    3.单链表查询(按值查询)

    LNode *LocateElem(LinklList L,int e)
    {
        LinklList p; 
        p = new LNode; //new 一个p结点
        for(p=L->next;p!=NULL;p=p->next) //遍历链表
            if(p->data == e) //如果找到了
            {
                printf("%d\n",p->data);//就输出p结点的值域
                return p;
            }
    }
    
    单链表插入

    4.单链表插入

    Status LinkInsert(LinklList &L,int i,int e)
    {
        LinklList p,s;
        p = new LNode;//new 一个p结点
        p = L->next; //p结点指向链表第一个结点
        for(int j = 1;j<=i-1; j++ )//遍历
        {
            p = p->next;
            if(!p)
                return ERROR;
        }
        s = new LNode; //new 一个s结点
        s->data = e; //s结点的值域等于要插入的数据
        if(i == 1)//特殊情况,当要插入的位置是第一位时
        {
            s->next = L->next; //s的next域等于头结点L的next域
            L->next = s; //头结点的next域等于s结点
            return OK;
        }
        s->next = p->next; //一般情况
        p->next = s;
        return OK;
    }//插入
    
    单链表删除

    5.单链表的删除

    Status LinkDelete(LinklList &L,int i)
    {
        LinklList p,q;
        p = new LNode; //new 一个p结点
        p = L->next; //p结点为链表中的第一个结点
        if(i<1)
            return ERROR;
        for(int j = 1;j<=i-1; j++ )
            if(!p)
                return ERROR;
        q = new LNode; //new 一个q结点
        q = p->next; //q节点指向被删除节点的下一个结点
        if(i == 1) //特殊情况
        {
            q = L->next; //q节点为链表第一个结点
            L->next = L->next->next;//头结点L的next域直接跳过被删除结点q,等于结点q的next域
            delete q;//释放空间
            return OK;
        }
        p->next = p->next->next;//一般情况
        delete q;
        return OK;
    }//删除
    
    前插法创建单链表

    6.前插法创建链表

    void CreateList_H(LinklList &L,int n)
    {
        LinklList p;
        L = new LNode; //new 一个头结点L
        L->next = NULL; //头结点L的next域为空,相当于空链表
        for(int i = 0; i < n; i++)//遍历
        {
            p = new LNode; //new 一个p结点
            scanf("%d",&p->data);  //读入p结点的值域
            p->next = L->next;   //p的next域赋值为L的next域
            L->next = p;   //L的next域指向结点p
        }
    }
    
    C++完整代码
    #include<cstdio>
    #include<iostream>
    using namespace std;
    #define maxsize 10010
    #define OK 1
    #define ERROR 0
    #define OVERFLOW -1
    
    typedef int Status;
    
    int e;
    int n;
    
    typedef struct LNode
    {
        int data;
        struct LNode *next;
    }LNode, *LinklList;
    
    //LinklList *p,*L;
    //p = new LNode;
    
    Status  InitList(LinklList &L)
    {
        L = new LNode;
        L->next = NULL;
        return OK; 
    }//初始化
    
    Status GetElem(LinklList L,int i,int &e)
    {
        LinklList p;
        p = new LNode;
        p = L->next;
        if(i<=0)
            return ERROR;
        for(int j=1;j<=i;j++)
        {
            p = p->next;
            if(!p)
                return ERROR;
        }
        e = p->data;
        return OK;
    }//取值
    
    LNode *LocateElem(LinklList L,int e)
    {
        LinklList p;
        p = new LNode;
        for(p=L->next;p!=NULL;p=p->next)
            if(p->data == e)
            {
                printf("%d\n",p->data);
                return p;
            }
    }
    
    Status LinkInsert(LinklList &L,int i,int e)
    {
        LinklList p,s;
        p = new LNode;
        p = L->next;
        for(int j = 1;j<=i-1; j++ )
        {
            p = p->next;
            if(!p)
                return ERROR;
        }
        s = new LNode;
        s->data = e;
        if(i == 1)
        {
            s->next = L->next;
            L->next = s;
            return OK;
        }
        s->next = p->next;
        p->next = s;
        return OK;
    }//插入
    
    Status LinkDelete(LinklList &L,int i)
    {
        LinklList p,q;
        p = new LNode;
        p = L->next;
        if(i<1)
            return ERROR;
        for(int j = 1;j<=i-1; j++ )
            if(!p)
                return ERROR;
        q = new LNode;
        q = p->next;
        if(i == 1)
        {
            q = L->next;
            L->next = L->next->next;
            delete q;
            return OK;
        }
        p->next = p->next->next;
        delete q;
        return OK;
    }//删除
    
    void CreateList_H(LinklList &L,int n)
    {
        LinklList p;
        L = new LNode;
        L->next = NULL;
        for(int i = 0; i < n; i++)
        {
            p = new LNode;
            scanf("%d",&p->data);
            p->next = L->next;
            L->next = p;
        }
    }
    
    void travel(LinklList L)
    {
         LinklList p;
         p = new LNode;
         for(p = L->next;p!=NULL;p=p->next)
                printf("%d\n",p->data);
    }
    
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            LinklList L,p,q;
            int e;
            InitList(L);
            CreateList_H(L,n);
            travel(L);
            /*for(p = L->next;p!=NULL;p=p->next)
                printf("%d\n",p->data);*/
            LinkInsert(L,3,10);
            /*for(p = L->next;p!=NULL;p=p->next)
                printf("%d\n",p->data);*/
            travel(L);
            LinkDelete(L,1);
            /*for(p = L->next;p!=NULL;p=p->next)
                printf("%d\n",p->data);*/
            travel(L);
            LocateElem(L,10);
            e = 10;
            GetElem(L,3,e);
            printf("%d\n",e);
        }
        return 0;
    }
    

    吐槽一下,最近笔者开始使用ubuntu来作业,chromium很吃资源,经常时不时卡死,疯狂读硬盘,可怜我那个战斗了四年的5400转机械硬盘,年后该考虑加根内存,上个固态。

    最近很火的鹦鹉兄弟表情

    暂告一段落
    END.

    相关文章

      网友评论

        本文标题:数据结构 线性表 链式存储结构

        本文链接:https://www.haomeiwen.com/subject/khefbttx.html