zoukankan      html  css  js  c++  java
  • 数据结构(C语言版)-第2章 线性表

    image

    image

    image

    #define  MAXSIZE 100     //最大长度
    typedef  struct {
      ElemType  *elem;     //指向数据元素的基地址
      int  length;          //线性表的当前长度                                                      
     }SqList;

    例子

    #define MAXSIZE 10000    //图书表可能达到的最大长度 
    typedef struct            //图书信息定义
    { 
       char no[20];            //图书ISBN
       char name[50];        //图书名字
       float price;             //图书价格
    }Book; 
    typedef struct
    { 
       Book *elem;    //存储空间的基地址 
       int length;        //图书表中当前图书个数 
    }SqList;        //图书表的顺序存储结构类型为SqList

    线性表的重要基本操作

    1.  初始化    2.  取值   3.  查找    4.  插入   5.  删除

    初始化线性表L (参数用引用)

    Status InitList_Sq(SqList &L){    //构造一个空的顺序表L
        L.elem=new ElemType[MAXSIZE];   //为顺序表分配空间
        if(!L.elem) exit(OVERFLOW);       //存储分配失败
        L.length=0;                      //空表长度为0
        return OK;
    }

    初始化线性表L (参数用指针)

    Status InitList_Sq(SqList *L){    //构造一个空的顺序表L
        L-> elem=new ElemType[MAXSIZE];   //为顺序表分配空间
        if(! L-> elem) exit(OVERFLOW);       //存储分配失败
        L-> length=0;                      //空表长度为0
        return OK;
    }

    销毁线性表L

    void DestroyList(SqList &L)
    {
      if (L.elem) delete[]L.elem;    //释放存储空间
    }

    清空线性表L

    void ClearList(SqList &L) 
    {
       L.length=0;                //将线性表的长度置为0
    }

    判断线性表L是否为空

    int IsEmpty(SqList L)
    {
      if (L.length==0) return 1;      
       else return 0;
    }

    获取线性表L中的某个(第i 个)数据元素的内容

    int GetElem(SqList L,int i,ElemType &e)
    {
      if (i<1||i>L.length) return ERROR;   
       //判断i值是否合理,若不合理,返回ERROR
      e=L.elem[i-1];   //第i-1的单元存储着第i个数据
      return OK;
    }

    在线性表L中查找值为e的数据元素

    int LocateELem(SqList L,ElemType e)
    {
      for (i=0;i< L.length;i++)
          if (L.elem[i]==e) return i+1; //返回是第几个元素               
      return 0;
    }

    在线性表L中第i个数据元素之前插入数据元素e

    Status ListInsert_Sq(SqList &L,int i ,ElemType e){
       if(i<1 || i>L.length+1) return ERROR;             //i值不合法
       if(L.length==MAXSIZE) return ERROR;    //当前存储空间已满     
       for(j=L.length-1;j>=i-1;j--) 
           L.elem[j+1]=L.elem[j];    //插入位置及之后的元素后移
        L.elem[i-1]=e;                     //将新元素e放入第i个位置
      ++L.length;                 //表长增1
      return OK;
    }
    //见下图

    image

    (1)判断插入位置i 是否合法。
    (2)判断顺序表的存储空间是否已满。     
    (3)将第n至第i 位的元素依次向后移动一个位置,空出第i个位置。
    (4)将要插入的新元素e放入第i个位置。
    (5)表长加1,插入成功返回OK。

    若插入在尾结点之后,则根本无需移动(特别快);若插入在首结点之前,则表中元素全部后移(特别慢);若要考虑在各种位置插入(共n+1种可能)的平均移动次数,该如何计算?

    image

     将线性表L中第i个数据元素删除

    Status ListDelete_Sq(SqList &L,int i){
       if((i<1)||(i>L.length)) return ERROR;     //i值不合法
       for (j=i;j<=L.length-1;j++)                   
        L.elem[j-1]=L.elem[j];       //被删除元素之后的元素前移  
       --L.length;                         //表长减1
      return OK;
    }

    image

    (1)判断删除位置i 是否合法(合法值为1≤i≤n)。
    (2)将欲删除的元素保留在e中。     
    (3)将第i+1至第n 位的元素依次向前移动一个位置。
    (4)表长减1,删除成功返回OK。

    若删除尾结点,则根本无需移动(特别快);若删除首结点,则表中n-1个元素全部前移(特别慢);若要考虑在各种位置删除(共n种可能)的平均移动次数,该如何计算?

    image

    查找、插入、删除算法的平均时间复杂度为O(n),顺序表的空间复杂度S(n)=O(1)(没有占用辅助空间)

    image

    2.5 线性表的链式表示和实现

    链式存储结构:结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻。线性表的链式表示又称为非顺序映像或链式映像。
    image

    各结点由两个域组成:
    数据域:存储元素数值数据
    指针域:存储直接后继结点的存储位置

    结点:数据元素的存储映像。由数据域和指针域两部分组成

    单链表、双链表、循环链表:
    结点只有一个指针域的链表,称为单链表或线性链表
    有两个指针域的链表,称为双链表
    首尾相接的链表称为循环链表

    循环链表:

    image

    image

    image

    有头结点时,当头结点的指针域为空时表示空表

    头结点的数据域可以为空,也可存放线性表长度等附加信息,但此结点不能计入链表长度值。

    image

    2.5.1 单链表的定义和实现

    image

    单链表是由表头唯一确定,因此单链表可以用头指针的名字来命名
    若头指针名是L,则把链表称为表L

    typedef struct LNode{
         ElemType   data;       //数据域
         struct LNode  *next;   //指针域
    }LNode,*LinkList;   // *LinkList为Lnode类型的指针

    若p->data=ai, 则p->next->data=ai+1

    image

    2.5.2 单链表基本操作的实现

    1.  初始化   2.  取值      3.  查找       4.  插入       5.  删除

    1.初始化(构造一个空表 )
    【算法步骤】
    (1)生成新结点作头结点,用头指针L指向头结点。
    (2)头结点的指针域置空。

    Status InitList_L(LinkList &L){ 
       L=new LNode;                        
       L->next=NULL;     
       return OK; 
    }

    销毁

    Status DestroyList_L(LinkList &L){
        LinkList p;
           while(L)
            {
                p=L;  
                L=L->next;
                delete p;  
            }
         return OK;
    }

    清空(链表仍在)

    Status ClearList(LinkList & L){
      // 将L重置为空表 
       LinkList p,q;
       p=L->next;   //p指向第一个结点
       while(p)       //没到表尾 
          {  q=p->next; delete p;     p=q;   }
       L->next=NULL;   //头结点指针域为空 
       return OK;
    }

    求表长

    int  ListLength_L(LinkList L){
    //返回L中数据元素个数
        LinkList p;
        p=L->next;  //p指向第一个结点
         i=0;             
         while(p){//遍历单链表,统计结点数
               i++;
              p=p->next;    } 
        return i;                             
    }

    判断表是否为空

    int ListEmpty(LinkList L){
    //若L为空表,则返回1,否则返回0
       if(L->next)   //非空
         return 0;
     
    else
         return 1;
    }

    2. 取值(根据位置i获取相应位置数据元素的内容)

    链表的查找:要从链表的头指针出发,顺着链域next逐个结点往下搜索,直至搜索到第i个结点为止。因此,链表不是随机存取结构

    //获取线性表L中的某个数据元素的内容
    Status GetElem_L(LinkList L,int i,ElemType &e){ 
        p=L->next;j=1; //初始化
         while(p&&j<i){    //向后扫描,直到p指向第i个元素或p为空 
           p=p->next; ++j; 
         } 
         if(!p || j>i)return ERROR; //第i个元素不存在 
         e=p->data; //取第i个元素 
         return OK; 
    }//GetElem_L
    //在线性表L中查找值为e的数据元素
    int LocateELem_L (LinkList L,Elemtype e) {
    //返回L中值为e的数据元素的位置序号,查找失败返回0 
      p=L->next; j=1;
      while(p &&p->data!=e)  
            {p=p->next;  j++;}                  
      if(p) return j; 
      else return 0;
    }

    3. 插入(插在第 i 个结点之前)

    image

    //在L中第i个元素之前插入数据元素e 
    Status ListInsert_L(LinkList &L,int i,ElemType e){ 
         p=L;j=0; 
          while(p&&j<i−1){p=p->next;++j;}    //寻找第i−1个结点 
          if(!p||j>i−1)return ERROR;    //i大于表长 + 1或者小于1  
          s=new LNode;            //生成新结点s 
          s->data=e;                         //将结点s的数据域置为e 
          s->next=p->next;                     //将结点s插入L中 
          p->next=s; 
          return OK; 
    }//ListInsert_L

    5. 删除(删除第 i 个结点)

    image

    //将线性表L中第i个数据元素删除
     Status ListDelete_L(LinkList &L,int i,ElemType &e){
        p=L;j=0; 
        while(p->next &&j<i-1){//寻找第i个结点,并令p指向其前驱 
            p=p->next; ++j; 
        } 
        if(!(p->next)||j>i-1) return ERROR; //删除位置不合理 
        q=p->next; //临时保存被删结点的地址以备释放 
        p->next=q->next;     //改变删除结点前驱结点的指针域 
        e=q->data;     //保存删除结点的数据域 
        delete q;     //释放删除结点的空间 
     return OK; 
    }//ListDelete_L

    单链表的建立(前插法)

    image

    void CreateList_F(LinkList &L,int n){ 
         L=new LNode; 
          L->next=NULL; //先建立一个带头结点的单链表 
          for(i=n;i>0;--i){ 
            p=new LNode; //生成新结点 
            cin>>p->data; //输入元素值 
            p->next=L->next;L->next=p;     //插入到表头 
         } 
    }//CreateList_F

    单链表的建立(尾插法)

    image

    void CreateList_L(LinkList &L,int n){ 
          //正位序输入n个元素的值,建立带表头结点的单链表L 
          L=new LNode; 
          L->next=NULL;     
          r=L;     //尾指针r指向头结点 
          for(i=0;i<n;++i){ 
            p=new LNode;         //生成新结点 
            cin>>p->data;           //输入元素值 
            p->next=NULL; 
           r->next=p;             //插入到表尾 
            r=p;     //r指向新的尾结点 
          } 
    }//CreateList_L

    2.5.3 循环链表

    image

    对循环链表,有时不给出头指针,而给出尾指针可以更方便的找到第一个和最后一个结点
    image

    开始结点:rear->next->next
    终端结点:rear

    循环链表的合并

    image
    image

    2.5.4 双向链表

    typedef struct DuLNode{
        ElemType   data;              
        struct DuLNode  *prior;  
        struct DuLNode  *next;  
    }DuLNode, *DuLinkList


    image

    image

    双向链表的插入
    image

    Status ListInsert_DuL(DuLinkList &L,int i,ElemType e){
       if(!(p=GetElemP_DuL(L,i))) return ERROR;
        s=new DuLNode; 
       s->data=e;
       s->prior=p->prior;  
       p->prior->next=s;
       s->next=p;  
       p->prior=s;
       return OK;
    }

    双向链表的删除
    image

    Status ListDelete_DuL(DuLinkList &L,int i,ElemType &e){
       if(!(p=GetElemP_DuL(L,i)))     return ERROR;
       e=p->data;
       p->prior->next=p->next;
       p->next->prior=p->prior;
       delete p; 
       return OK;
    }

    总结

    image

  • 相关阅读:
    移动端开发rem布局之less+媒体查询布局的原理步骤和心得
    前端实现文件下载方式总汇
    如何能提高CSS编写技巧?提高Web前端开发效率
    常用的CSS命名规则
    CSS背景background
    CSS盒子模型
    简单的树形菜单如何写?
    彻底掌握css动画【transition】
    首页白屏优化实践
    我来聊聊面向模板的前端开发
  • 原文地址:https://www.cnblogs.com/mohuishou-love/p/10319585.html
Copyright © 2011-2022 走看看