数据结构c++ 随堂笔记2

来源:互联网 发布:macbook视频制作软件 编辑:程序博客网 时间:2024/06/11 22:53

本章的基本内容是:

Ø  线性表的逻辑结构

Ø   线性表的顺序存储及实现

Ø   线性表的链接存储及实现

Ø   顺序表和单链表的比较

Ø   线性表的其他存储及实现

线性表

线性表的定义

线性表:简称表,是nn≥0)个具有相同类型的数据元素的有限序列。

线性表的长度:线性表中数据元素的个数。

空表:长度等于零的线性表,记为:L=( )。

非空表记为:L=(a1, a2, …, ai-1, ai , …, an)

其中,ai(1≤in)称为数据元素;

下角标i 表示该元素在线性表中的位置或序号。

线性表的特性

1.有限性:线性表中数据元素的个数是有穷的。

2.相同性:线性表中数据元素的类型是同一的。

3.顺序性:线性表中相邻的数据元素ai-1ai之间存在序偶关系(ai-1,ai),即ai-1ai的前驱,aiai-1的后继;a1 无前驱,an无后继,其它每个元素有且仅有一个前驱和一个后继。

线性表的抽象数据类型定义

DestroyList

   前置条件:表已存在

   输入:无

   功能:销毁表

   输出:无

   后置条件:释放表所占用的存储空间

Length

   前置条件:表已存在

    输入:无

    功能:求表的长度

    输出:表中数据元素的个数                                             

    后置条件:表不变

线性表的抽象数据类型定义

ADT List

Data

     线性表中的数据元素具有相同类型,

     相邻元素具有前驱和后继关系

Operation

InitList

   前置条件:表不存在

   输入:无

   功能:表的初始化

   输出:无

   后置条件:建一个空表

线性表的抽象数据类型定义

Get

   前置条件:表已存在

   输入:元素的序号i

   功能:在表中取序号为i的数据元素

   输出:若i合法,返回序号为i的元素值,否则抛出异常

   后置条件:表不变

Locate

   前置条件:表已存在

   输入:数据元素x

   功能:在线性表中查找值等于x的元素

   输出:若查找成功,返回x在表中的序号,否则返回0

   后置条件:表不变

Insert

         前置条件:表已存在

         输入:插入i;待插x

         功能:在表的第i个位置处插入一个新元素x

         输出:若插入不成功,抛出异常

   后置条件:若插入成功,表中增加一个新元素

Delete

         前置条件:表已存在

         输入:删除位置i

         功能:删除表中的第i个元素

   输出:若删除成功,返回被删元素,否则抛出异常

后置条件:若删除成功,表中

Empty

   前置条件:表已存在

   输入:无

   功能:判断表是否为空

   输出:若是空表,返回1,否则返回0

   后置条件:表不变

ADT

进一步说明:

(1)线性表的基本操作根据实际应用是而定;

(2)复杂的操作可以通过基本操作的组合来实现;

(3)对不同的应用,操作的接口可能不同。

存储结构和存取结构

存储结构是数据及其逻辑结构在计算机中的表示;

存取结构是在一个数据结构上对查找操作的时间性能的一种描述。

“顺序表是一种随机存取的存储结构”的含义为:在顺序表这种存储结构上进行的查找操作,其时间性能为O(1)。

顺序表类的声明

const int MaxSize=100; 

template <class T>           //模板类

class SeqList

{

 public:

    SeqList( ) ;                    //构造函数

    SeqList(T a[ ], int n);      

    ~SeqList( ) ;                  //析构函数

    int Length( );

    T Get(int i);

    int Locate(T x );

    void Insert(int i, T x); 

    T Delete(int i);       

 private:

    T data[MaxSize];

    int length;

};

顺序表的实现——有参构造函数

template <class T> 

SeqList::SeqList(T a[ ], int n)

      if (n>MaxSize) throw "参数非法";

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

             data[i]=a[i];

      length=n;

 }

顺序表的实现——插入

算法描述——伪代码

1. 如果表满了,则抛出上溢异常;

2. 如果元素的插入位置不合理,则抛出位置异常;

3. 将最后一个元素至第i个元素分别向后移动一个位置;

4. 将元素x填入位置i处;

5. 表长加1;

算法描述——C++描述

template <class T> 

void SeqList::Insert(int i, T x)

{

     if (length>=MaxSize) throw "上溢";

     if (i<1 | | i>length+1) throw "位置";

     for (j=length; j>=i; j--)

           data[j]=data[j-1];

     data[i-1]=x;

     length++;

}

时间性能分析

最好情况(i=n+1):

       基本语句执行0次,时间复杂度为O(1)。

最坏情况(i=1):

       基本语句执行n+1次,时间复杂度为O(n)。

平均情况(1≤in+1):

        时间复杂度为O(n)。

顺序表的实现——按值查找

template <class T> 

int SeqList::Locate(T x)

{

    for (i=0; i<length; i++)

        if (data[i]==x) return i+1;

    return 0;         

}

顺序表的优缺点

Ø  顺序表的优点:

⑵     无需为表示表中元素之间的逻辑关系而增加额外的存储空间;

⑵随机存取:可以快速地存取表中任一位置的元素。

Ø  顺序表的缺点:

⑴插入和删除操作需要移动大量元素;

⑵表的容量难以确定,表的容量难以扩充;

⑶     造成存储空间的碎片。

单链表

存储特点:

1.            逻辑次序和物理次序

    不一定相同。

2.元素之间的逻辑关系

    用指针表示。

单链表类的声明

template <class T>

class LinkList

{  

public:

     LinkList( );

     LinkList(T a[ ], int n);

     ~LinkList( );

     int Length( );         

     T Get(int i);          

     int Locate(T x);      

     void Insert(int i, T x);  

     T Delete(int i);       

     void PrintList( );          

private:

     Node<T> *first;

};

单链表的实现——按位查找

算法描述——伪代码

1. 工作指针p初始化; 累加器j初始化;

2. 循环直到p为空或p指向第i个结点

2.1 工作指针p后移;

2.2 累加器j加1;

3. 若p为空,则第i个元素不存在,抛出查找位置异常;否则查找成功,返回结点p的数据元素;

算法描述——C++描述

template <class T> 

T LinkList::Get(int i)

{

     p=first->next;  j=1; 

     while (p &&j<i)   

     {

         p=p->next;

         j++;     

     }

     if (!p)   throw "位置";

     else returnp->data; 

}

单链表的实现———插入

算法描述——伪代码

1. 工作指针p初始化;累加器j清零;

 2. 查找第i-1个结点并使工作指针p指向该结点;

 3. 若查找不成功,说明插入位置不合理,抛出插入位置异常;否则,

     3.1 生成一个元素值为x的新结点s;

          3.2 将新结点s插入到结点p之后;

单链表的实现———删除

算法描述——伪代码

1.工作指针p初始化;累加器j清零;

 2. 查找第i-1个结点并使工作指针p指向该结点;

 3. 若p不存在或p不存在后继结点,则抛出位置异常;

     否则,

         3.1 暂存被删结点和被删元素值;

         3.2 摘链,将结点p的后继结点从链表上摘下;

         3.3 释放被删结点;

         3.4 返回被删元素值;

算法描述——C++描述

template <class T> 

T LinkList::Delete(int i)

{   

    p=first ; j=0; 

    while (p &&j<i-1)

    {

         p=p->next;

         j++;

     }

   if (!p | | !p->next)

        throw “位置”;

   else { 

         q=p->next;

         x=q->data;  

         p->next=q->next;  

         delete q;

         return x;

    }

 }

单链表的实现———构造函数

template <class T> 

LinkList:: LinkList(T a[ ], int n)

{      

    first=new Node<T>;

    first->next=NULL;  

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

    {

        s=new Node<T>;

        s->data=a[i];  

       s->next=first->next;       

        first->next=s;

     }

 }

算法设计的一般步骤:

第一步:确定入口(已知条件)、出口(结果);

第二步:根据一个小实例画出示意图;

第三步:① 正向思维:选定一个思考问题的起点,逐步提出问题、解决问题;②逆向思维:从结论出发分析为达到这个结论应该先有什么;③正逆结合;

第四步:写出顶层较抽象算法,分析边界情况;

第五步:验证第四步的算法;

第六步:写出具体算法;

第七步:进一步验证,手工运行。

时间性能比较

时间性能是指实现基于某种存储结构的基本操作(即算法)的时间复杂度。

按位查找:

Ø  顺序表的时间为(1),是随机存取;

Ø  单链表的时间为(n),是顺序存取。

插入和删除:

Ø  顺序表需移动表长一半的元素,时间为(n);

单链表不需要移动元素,在给出某个合适位置的指针后,插入和删除操作所需的时顺序表和单链表的比较⑴若线性表需频繁查找却很少进行插入和删除操作,或其操作和元素在表中的位置密切相关时,宜采用顺序表作为存储结构;若线性表需频繁插入和删除时,则宜采用单链表做存储结构。

⑵当线性表中元素个数变化较大或者未知时,最好使用单链表实现;而如果用户事先知道线性表的大致长度,使用顺序表的空间效率会更高。

总之,线性表的顺序实现和链表实现各有其优缺点,不能笼统地说哪种实现更好,只能根据实际问题的具体需要,并对各方面的优缺点加以综合平衡,才能最终选定比较适宜的实现方法。

0 0