DS博客作业02-线性表

一曲冷凌霜 提交于 2020-03-08 23:22:33

0.PTA得分截图

1.本周学习总结

1.1 总结线性表内容

  • 什么是线性表?

    • 定义:
      线性表是具有相同特性的数据元素的一个有限序列。

    • 线性表一般表示:
      (a1,a2,a3...ai..an)
      这里a1为表头元素,an为表尾元素。

    • 线性表特征:
      1.元素个数n——表长度; n=0——空表
      2.1<i<n时
      a[i]的直接前驱是a[i-1],a[1]无直接前驱
      a[i]的直接后继是a[i+1],
      a[n]无直接后继
    • 3.元素同构,且不能出现缺项
  • 线性表的抽象数据类型描述

ADT List
{
    数据对象D={ai|ai∈Elemset, i=1,2, . n, n≥0}
    数据关系: R={<ai-1, ai>|ai-1,ai∈D, i=2, .., n}
    基本操作:
       InitList (&L) :构造一个空的线性表L
       DestroyList (&L) :销毁线性表L占用内存空间
       ListEmpty(L):若线性表L为空表,则返回TRUE,否则返回FALSE
       ListLenght(L):返回线性表L数据元素个数
       GetElem(L, i, &e):用e返回线性表L中第i个数据元素的值
       LocatElem(L,e):返回L中第一个值域与e相等的逻辑位序。若这样的元素不存在,则返回值为0。
       ListInsert(&L, i,e) :
       ListDelete(&L, i, &e) :
}
//采自数据结构课堂派课件《第二章线性表--顺序表-预习》
  • 顺序表:
    • 存储结构:把线性表中的所有元素按照顺序存储方法进行存储的结构成为顺序表。
    • 特点:
      1、实现逻辑上相邻——物理地址相邻
      2、实现随机存取
    • 顺序表定义:
#define MaxSize 50
typedef int ElemType; //ElemType栈区类型实际上是int
typedef struct{
    ElemType data[MaxSize]; //存放顺序表中的元素
    int length;//顺序表的长度
}SqList; //SequenceList,顺序表

这里数组的大小要大于等于线性表的长度,也就是MaxSize

  • 顺序表插入
    在L->data的第i个位置插入e元素

实现代码:

bool ListInsert(List &L, int i, ElemType e)
{ 
    int j;
    if (i<1||i>L- > length+1)
    return false;//参数错误时返回false
    i-; //将顺序表逻辑序号转化为物理序号
    for (j=L->length; j>i;j--) //将data[i.. n]元素后移一个位置
    L->data[j]=L->data[j-1];
    L->data[i]=e;//插入元素e
    L-> | ength++; //顺序表长度增1
    return true;//成功插入返回true

顺序表插入的时间复杂度为:0(n)

  • 顺序表删除
    删除第i个元素:

    实现代码:
bool ListDelete(List &L,int i,ElemType &e)
{
    if (i<1 ||i>L->length) //删除位置不合法
        return false;
    i-- ;/ /将顺序表逻辑序号转化为物理序号
    e=L->data[i] ;
    for (int j=i;j<L->length-1;j++)
        L->data[j]=L->data [j+1];
    L->length--; //顺序表长度减1
    return true ;
}

顺序表删除的时间复杂度为:0(n)

  • 链表——线性表的链式存储
    • 结构体定义:
    typedef struct LNode 
    {
      EIemType data;//数据域
      struct LNode *next;//指针域
    }LNode,*LinkList;
    • 头指针、头结点
      以线性表中第一个数据元素a1的存储地址作为线性表的地址,称作线性链表的头指针。有时为了操作方便,在第一个结点之前虛加一个“头结点”,以指向头结点的指针为链表的头指针。
    • 在链表中设置头结点的好处:
      1.便于首元结点的处理
      首元结点的地址保存在头结点的指针域中,所以在链表的第一个位置上的操作和其它位置一致,无须进行特殊处理;
      2.便于空表和非空表的统一处理
      无论链表是否为空,头指针都是指向头结点的非空指针,因此空表和非空表的处理也就统一了。
  • 链表的头插法——新增节点从链表头部插入
    • 基本图示:
    • 实现代码:
//将数组a中的元素赋值到链表L中,采用头插法所用代码
void CreateListF(LinkList &L,ElemType a[],int n)
{
    int i;
    L=new LNode;
    L->next=NULL;
    LinkList nodePtr;
    for(i=0;i<n;i++)
    {
        nodePtr=new LNode; 
        nodePtr->data=a[i];
        nodePtr->next=] L->next;
        L->next= nodePtr;
    }
}

这里链表每个节点务必都是动态申请,C语言中动态申请用malloc,而C++语法中用new,new的用法比malloc更简单,更容易使用,比如上述代码的nodePtr=new LNode;在C语言中相当于nodePtr=(LinkList)malloc(sizeof(LNode));
创建链表的时间复杂度:O(n)。

  • 链表的尾插法——新增节点从链表尾部插入
    • 图示:

      新节点插到当前链表的表尾上必须增加一个尾指针TailPtr,使其始终指向当前链表的尾节点。
    • 实现代码:
void CreateListR(LinkList &L,ElemType a[],int n)
{
    int i;
    LinkList nodePtr,tailPtr;
    L=new LNode;
    L->next=NULL;
    tailPtr=L;//尾指针
    for(i=0;i<n;i++) 
    {
        nodePtr= new LNode;
        nodePtr->data=a[i];
        tailPtrPtr->next=nodePtr;//尾部插入新结点
        tailPtr=nodePtr;
    }
    nodePtr->next= NULL;
}

尾插法创建链表的时间复杂度:O(n),与头插法一样。

  • 链表的插入
    在链表L的指针p后面插入一个s所指向的结点

    • 实现代码
    void LinkInsert(LinkList &L,LinkList &s,LinkList &p)
    {
      s->next=p->next;
      p->next=s;
    }
  • 链表的删除
    删除在链表的第i个结点

    • 实现代码
    bool ListDelete_ L(LinkList &L,int i)
    {
      int j=0;
      LinkList p=L,s,q;
      while(p&&j<i-1)
      {
          p=p->next;j++;
      }
      if(p==NULL) 
      return false;
      q=p->next; //第i个位置
    
      p->next=q->next;//改变指针关系,
      delete q;
      return true;
    }
  • 有序单链表数据插入、删除,有序表合并

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!