美文网首页
3.线性表--大话数据结构

3.线性表--大话数据结构

作者: 小李同学今天博学了吗 | 来源:发表于2020-02-19 13:24 被阅读0次

    定义

    若将线性表记为(a1,....ai-1,ai,ai+1,....,an),则表中ai-1领先于ai,ai领先于ai+1,称ai-1是ai 的直接前驱元素,ai+1是ai的直接后继元素,当i = 1,2, ... n-1时,ai有且仅有一个直接后继,当i = 2,3,...,n时,ai有且仅有一个直接前驱, (通俗来说,就是用一根线将数据串联起来)

    线性表的顺序存储结构:

    指的是用一段地址连续的存储单元依次存储线性表的数据元素(也就是数组)

    优点:1.无须为表示表中元素之间的逻辑关系而增加额外的存储空间 2.可以快速存取表中任一位置的元素
    缺点:1.插入和删除操作需要移动大量元素 2.当线性表长度变化较大时,难以确定存储空间的容量
    3.造成存储空间的浪费

    线性表的链式存储结构

    就是链表中包含数据域、指针域,当个数据叫做结点,只包含一个指针域的叫做单链表

    1.头指针:

    链表第一个结点的存储位置叫做头指针,就相当于 struct Node * n = createNode();n 就为头指针

    2.头结点:

    在链表的第一个结点前附设一个结点,称为头结点,就是在第一个存储数据结点前面的那个结点,这个结点数据域不存数据

    3.异同:

    头指针:
    1.头指针是指链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针
    2.头指针具有标识意义,所以用头指针冠以链表的名字
    3.无论链表是否为空,头指针均不为空,头指针是链表的必要元素

    头结点:
    1.头结点是为了操作的统一和方便而设立的,放在第一个结点之前,其数据域一般无意义
    2.有了头结点,对在第一元素结点前插入结点和删除第一结点,其操作与其他结点的操作就统一了,
    3.头结点不一定时链表的必须要素

    4.当链表的整表创建

    4.1头插法

    void CreateListHead(LinkList *L,int n){
        LinkList p;
         int i;
         srand(time(0)); //随机产生数
        (*L) = (LinkList) malloc(sizeof(Node));
        (*L)->next = NULL;
      
        for(i = 0;i<n;i++){
            p = (LinkList)malloc(sizeof(Node));
            p->data = rand()%100 +1;
            p->next = (*L)->next;
            (*L)->next = p;
        }
    }
    

    4.2尾插法

    void CreateListHead(LinkList *L,int n){
        LinkList p,r;
         int i;
         srand(time(0)); //随机产生数
        (*L) = (LinkList) malloc(sizeof(Node));
        (*L)->next = NULL;
      
        for(i = 0;i<n;i++){
            p = (LinkList)malloc(sizeof(Node));
            p->data = rand()%100 +1;
            r->next = p;
             r = p;
        }
      r->next = NULL;
    }
    

    4.2整表删除

    Status ClearList(LinkList *L){
    
        LInkList p, q;
        p = (*L)->next;
      while(p){
          q = p->pnext;
          free(p);
          p = q;
      }
    (*L)->next = NULL;
    return OK;
    }
    
    5.静态链表

    定义:用数组描述的链表,这种方法也叫游标实现法
    我们对数组的第一个和最后一个元素作为特殊元素处理,不存数据,我们通常把未被使用的数组元素称为备用链表,而数组第一个元素,即下标为0的元素的cur就存放备用链表的第一个结点的下标,而数组的最后一个元素的cur则存放第一个有数值的元素下标,相当于单链表的头结点作用。


    d9e7cb8f702284fdda1d4e654142323.jpg
    
    # define MAXSIZE 1000
    typedef stuct{
      ElemType data;
      int cur;
    }Component,StaticLinkList[MAXSIZE];
    //将这个链表初始化
    Status InitList(StaticLinkList space){
        int i;
        for(i = 0;i< MAXSIZE -1;i++){
            space[i].cur = i+1;
          }
    space[MAXSIZE].cur = 0;
    return OK;
    }
    

    5.1静态链表的插入操作


    8e6fe780d39cd58116aaa3997d46ce3.jpg
    // 这个函数是得到下一个存储空间的下标
    int Malloc_SLL(StaticLinkList space){
      int i = space[0].cur;
      if(space[0].cur)
            space[0].cur = space[i].cur;
    
    return i;
    
    }
    
    Status ListInsert(StaticLinkList L,int i,ElemType e){
      int j,k,l;
      k = MAX_SIZE -1; //得到的是第一个有值元素的下标
      if(i < 1 || i > ListLength(L) + 1)
            return ERROR;
      j = Malloc_SSL(L); // 得到插入的下标,并将0下标中备用链表更新;
      if(j){ // 在C 语言中,除了0,都是真
        L[j].data = e;  // 赋值
         //  找到插入下标之前的元素下标 
        for(l = 1;l <= i -1;l++){
          k = L[k].cur;
          }
          //将插入前的那个元素存储的下标赋值给插入的元素,即插入元素执行下一个元素
          L[j].cur = L[k].cur;
          // 前一个元素指向插入元素
          L[k].cur = j;
          return OK;
    
      }
    }
    

    5.2静态链表的删除操作

    // 删除在L中第i 个数据元素e
     Status ListDelete(StaticLinkList L,int i){
        int j,k;
        if(i < 1 || i > ListLength(L))
            return ERROR;
         k = MAX_SIZE -1;
          for(j = 1;j<= i -1;j++)
                k = L[k].cur;
          j = L[k].cur;
          L[k].cur = L[j].cur;
          Free_SSL(L,j);
          return OK;
      }
    
    void Free_SSL(StaticLinkList space,int k){
      space[k].cur = space[0].cur;
      space[0].cur = k;
     }
    
    //静态链表长度
    int ListLength(StaticLinkList L){
      int j = 0;
      int i = L[MAXSIZE -1].cur;
      while(i){
        i = L[i].cur;
        j++;
      }
    
    return j;
    }
    
    6.循环链表

    定义:将单链表中终端结点的指针端由空指针改为指向头结点,就是整个单链表形成一个环,这种头尾相接的单链表称为单循环链表。


    3a9505df3e84263ef3568f732a6a1f7.jpg

    将两个循环链表合为一个的代码

    p = rearA->next; //保存A的头结点
    rearA->next= rearB->next->next; // 使A指向B的第一个有值元素,
    q = rearB->next;//将头结点赋值给q
    rearB->next = p;//将B指向A的头结点
    free(q);//释放B的头结点
    
    7.双向链表

    定义:是在前链表的每个结点中,在设置一个指向其前驱结点的指针域

      ElemType data;
      struct DulNode *prior;
      struct DulNode *next;
    }DulNode,* DuLinkList;
    

    插入数据:先搞定插入结点的前驱和后继,再搞定后结点的前驱,最后解决前结点的后继


    cfd35ed398d3a35a044f405e1fe2e9d.jpg

    删除数据:记得free(p);


    fe66e15eb4e4d1666a2e761c41a845c.jpg

    相关文章

      网友评论

          本文标题:3.线性表--大话数据结构

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