数据结构与算法第二章——线性表

 

第二章线性表

线索Cues

笔记Notes

  • 2.1线性表的定义和特点

  • 2.2案例引入

  • 2.3线性学类型定义

  • 2.4线性表的顺序表示和实现

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

  • 2.6顺序表和链表的比较

  • 2.7线性表的应用

  • 2.8案例分析和实现

2.1线性结构特点

1、一个首一个尾

2、除首尾外其他结点只有一个直接前驱和一个直接后继。

线性结构包括线性表、堆栈、队列、字符串、数组,最常用的是线性表。

2.2案例引入

一元多项式的运算

稀疏多项式的运算

线性表P=((p1,e1),(p2,e2),…,(pm,em))

2.3线性表的存储类型与操作定义

线性表的存储结构

  • 顺序存储结构

  • 链式存储结构

2.4线性表顺序存储的实现

用一组地址连续的存储单元依次存储线性表的元素,可通过数组V[n]来实现。

线性表的重要的基本操作

  • 初始化

初始化、销毁、清空、求长,判断是否为空

初始化线性表L

方法一

Status InitList(SqList&L){  //构造一个空的顺序表L

L.elem=new ElemType[MAXSIZE];   //为顺序表分配空间

if(!L.elem) exit(OVERFLOW);    //分配失败

L.length=0;                             //空表长度为0;

return OK;

}

方法二

Status InitList_Sq(SqList *L){

L->elem = new ElemType[MAXSIZE];

if(!L->elem) exit(OVERFLOW);

L->length=0;

return OK;

}

 

删除线性表

void DestroyList(SqList &L){

if (L.elem)delete[ ]L.elem;

}

清空线性表L

void ClearList(SqList)

{

L.length=0;

}

求线性表的长度

int GetLength(SqList L)

{

return (L.length);

}

判断线性表L是否为空

int IsEmpty(SqList L)

{

if (L.length==0)

    return 1;

else

    return 0;

} 

  • 取值

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

int GetElem(SqList L,int I,ElemType &e)

{

if (i<1 || i>L.length) return ERROR;

e = L.elem[i-1];

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;

}
  • 插入

算法思路

1、判断插入位置i是否合法

2、判断顺序表的存储空间是否已满

3、将第n至第i位的元素依次向后移动一个位置,空出第i个位置

4、将要插入的新元素e放入第i个位置

5、表长加1,插入成功返回ok

Status ListInsert_Sq(SqList &L,int i,ElemType e){

if (i< || i>L.length+1) return ERROR;    //判断I的合法性

if(L.length==MAXSIZE) return ERRORS; //判断顺序表的存储空间是否已满

for(j=L.length-1;j>=i-1;j—)

    L.elem[j+i]=L.elem[j];

    L.elem[i-1]=e;

    ++L.length;

return OK;

}
  • 删除

Status ListDelete_Sq(SqList &L,int i){

if ((i<1)||(i<L.length)) return ERROR;

for(j=I;j<=L.length-1;j++)

    L.elem[j-1]=L.elem[j];    //被删除元素之后的元素前移

—L.length;

return OK;

}

 

 

2.5线性表链式存储的实现

在链表中设置头结点的好处

1、便于首结点的处理

首元结点的地址保存在头结点的指针域中,所以在链表的第一个位置上的操作与其他位置的一致,无须进行特殊处理。

2、便于空表与非空表的统一处理

无论链表是否为空,头指针都是指向头结点的非空指针,因此空表和非空表的处理也就统一了。

 

单链表存储结构定义

typedef struct LNode{

        ElemType    data;

        struct LNode    *next;

} LNode,*LinkList;

单链表

(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)  //while(L!=NULL)

         {

          p=L;

          L=L->next;

          delete p;

        }

        return 0;

}

清空

Status ClearList(LinkList &L){

        LinkList p,q;

         p=L->next;

         while(p)

         {

          q=p->next;

          delete p;

          p=q;

          }

          L->next=NULL;

          return OK;

}

求表长

int ListLength_L(LinkList L)

{

LinkList p;

  p=L->next;

  i=0;

  while(p){

      i++;

      p=p->next;

}

return i;

}

判断表是否为空

int ListEmpty(LinkList L)

{

  if(L->next)

    return 0;

  else

    return 1;

}

取值

Status GetElem_L(LinkList L,int I,ElemType &e){

  p=L->next ; j=1;  //初始化

   while(p&&j<i){

      p=p->next; ++j;

    }

   if(!p || j>I ) return ERROR; //第i个元素不存在

   e=p-data;   //取第i个元素

  return OK;

}

查找

LNode *LocateELem_L(LinkList L, Elemtype e)  //定义上带*号

{

  p=L->next;

  while(p&&p->data!=e)

       p=p->next;

  return p;     //返回的是数据元素的地址

}

//返回地址序号

int LocateELem_L(LinkList L,Elemtype e){

  p=L->next; j=1;

  while(p&&p->data!=e)

      {

       p=p->next; j++;

      }

   if(p) return j;

   else return 0;

}

插入

//在第i个元素之前插入

Status ListInsert_L(LinkList &L,int i,ElemType){

    p=L; j=0;

    while(p&&j<i-1){p=p->next; ++j}

    if(!p || j>i-1)  return ERROR;

    s=new LNode;

    s->date=e;

    s->next=p->next;

    p-next=s;

    return OK:

}

删除

Status ListDelete_L(LinkList &L,int i;ElemType  &e){

    p=L;j=0;

    while(p->next &&j<i-1){

        p=p->next; ++j;

     }

    if(!(p->next) || j>j-1) return ERROR;//

    q=p->next;

    p->next=q->next;

    e=q->data;

    delete q;

    return OK;

}

单链表的建立(前插法)

void CreateList_F(LinkList&L,int n){

    L=next LNode

    L->next=NULL;  //先建立一个带头结点的单链表

    for(I=n; I>0; —i){

        p=new LNode;  //生成新结点

        cin>>p->data;   //输入元素值

        p->next=L->next; L-next=p;   //插入到表头

     }

}

单链表的建立(尾插法)

void CreateList_L(LinkList &L, int n){

     L=new LNode;

     L->next=NULL;

     r=L;

     for(I=0;i<n;i++){

       p=new LNode;                       //生成新结点

       cin>>p->data;                        //输入元素值

       P->next=NULL; r->next=p;    //插入到表尾

       r=p;                                        //指向新的尾结点

}

}

双向链表

typedef struct DuLNode{

        ElemType data;

        struct DuLNode *prior;

        struct DuLNode *next;

}DuLNode,*DuLinkList

 

插入

Status ListInsert_DuL(DuLinkList &L,int i,ElemType e){

    if (!(p=GetElemP_DuL(L,i)))  rerutrn ERROR;

     s=new DuLNode;

     s->data=e;

     s->prior=p->prior;

     p->prior->next=s;

     s->next=p;

     p->prior=s;

    return OK;

}

2.6顺序表和链表的区别

查找元素顺序表的时间复杂度O(1),链表的时间复杂度为O(n)

插入删除顺序表的 时间复杂度为O(n),链表的时间复杂度为O(1)

2.7

线性表的合并

void union(List &La,List Lb){

  La_len=ListLength(La);

  Lb_len=ListLength(Lb);

  for(i=1;i<=Lb_len;i++){

    GetElem(Lb.i.e);

    if(!LocateElem(La,e))

         ListInsert(&La,++La_len,e);

  }

}

有序表的合并

void union(List &La,List Lb){

  La_len=ListLength(La);

  Lb_len=ListLength(Lb);

  for(i=1;i<=Lb_len;i++){

    GetElem(Lb.i.e);

    if(!LocateElem(La,e))

         ListInsert(&La,++La_len,e);

  }

}

有序链表的合并(允许有重复)

void MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc){

    pa=La->next; pb=Lb->next;

    pc=Lc=La;

    while(pa &&pb){

        if(pa->data<=pb->data){pc->next=pa; pc=pa;pa=pa->next;}

        else{pc->next=pb; pc=pb; pb=pb->next; }

     pc->next=pa?pa:pb;

     deleta Lb;

}

}

 

总结Summary

  • 重视逻辑结构

  • 掌握顺序存储和链式存储的增删查改

 

 

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值