[读书笔记]-大话数据结构-3-线性表-线性表的顺序存储

Posted zhaoxianyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[读书笔记]-大话数据结构-3-线性表-线性表的顺序存储相关的知识,希望对你有一定的参考价值。

线性表:零个或者多个元素的有限序列。包括顺序表和链表单向链表、循环链表、双向链表、循环双向链表

线性表的定义

    若将线性表记为(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有且仅有一个直接前驱。如下图

    线性表的个数n(n>=0)定义为线性表的长度,当n=0时,称为空表。

    在较复杂的线性表中,一个数据元素可以由若干个数据项组成。如下图

 

线性表的抽象数据类型

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

ADT  线性表(List)
Data
    \'\'\'线性表的数据对象集合为{a1,a2,...,an},每个元素的类型均为DataType。其中,除第一个元素a1外,每一个元素有且只有一个直接前驱元素,除了最后一个元素an外,每一个元素有且只有一个直接后继元素。数据元素之间的关系是一对一的关系。\'\'\'
Operation
    InitList(*L):   \'\'\'初始化操作,建立一个空的线性表L。\'\'\'
    ListEmpty(L):  \'\'\'若线性表为空,返回true,否则返回false.\'\'\'
    ClearList(*L):  \'\'\'将线性表清空。\'\'\'
    GetElem(L,i):  \'\'\'将线性表L中的第i个位置元素值返回。\'\'\'
    LocateElem(L,e):  \'\'\'在线性表中查找与给定值e相等的元素,如果查找成功,返回该元素在表中的序号表示成功;否则返回0表示失败。\'\'\'
    ListInsert(*L,i,e):  \'\'\'在线性表L中的第i个位置插入新元素e。\'\'\'
    ListDelete(*L,i):  \'\'\'删除线性表L中第i个位置元素,并返回其值。\'\'\'
    ListLength(L):   \'\'\'返回线性表L的元素个数。\'\'\'
endADT

     不同的线性表基本操作不同,上述操作是最基本的,实际中可能有更复杂的操作。例如实现两个线性表A和B的并集操作,使得A=AUB。

    假设La表示集合A,Lb表示集合B,并集的Python实现代码如下:

    def Union(self,lb):
        for i in range(1,lb.ListLength()+1):   #循环b列表
            e=lb.GetElem(i)                #取出第i个元素
            if self.LoacateElem(e)==0:     #如果该元素不在a中
                self.ListInsert(self.length+1, e)   #将e插入a

    上面定义的union操作用到了前面定义的 ListLength、GetElem、LocateElem和ListInsert操作。

线性表的顺序存储结构

    线性表的顺序存储结构,是指用一段地址连续的存储单元一次存储线性表的数据元素。 线性表(a1,a2,...,an)的顺序存储示意图如下:

线性表顺序存储代码(Python代码)

class SqList(object):
    def __init__(self,size=20):  #默认生成20个元素的线性表
        self.data=list(None for i in range(size))  #数据
        self.maxsize=size   #最大长度
        self.length=0       #当前长度

    可以看到描述线性表需要三个属性:

  • 存储空间的起始位置:数组data的存储位置
  • 线性表的最大存储容量:maxsize
  • 线性表的当前长度:length

    顺序存储的每个存储单元都有自己的编号,这个编号称为地址。Python中存储单元的编号从0开始,依次类推。从时间复杂度的角度来说,它的存取时间性能为O(1),如下图:

获得元素(GetElem)的代码实现

    def GetElem(self,i):   #Python没有指针,所以用返回的形式把值赋给e
        if i>self.length or i < 1:
            raise IndexError(\'Index is out of range...\')
        else:
            return self.data[i-1]  

顺序存储结构的插入与删除

插入

    线性表拆入元素时不能直接拆入,必须把插入位置后面每个元素依次后移,留出位置后再插入,插入操作思路:

  • 如果插入位置不合理,抛出异常
  • 如果线性表长度大于等于数组长度,则抛出异常或动态增加容量;
  • 从最后一个元素开始向前遍历到第I个位置,分别将它们都向后移动一个位置;
  • 将要插入的元素放到第i个位置处

插入数据(ListInsert)的实现代码

    def ListInsert(self, i, e):
        if i>self.length or i < 0:  #下标不在范围
            raise IndexError(\'Index out of range...\')
        elif self.length == self.maxsize:  #线性表已满
            self.data.append(e)   #此处可以动态增加线性表长度,也可以抛出异常
            self.maxsize+=1
            self.length+=1
        elif i <= self.length:
            for j in range(i-1,self.length)[::-1]: #第i到length个元素从后往前遍历  
                self.data[j+1]=self.data[j]        #元素依次后移
            self.data[i-1]=e               #第i个元素等于e
            self.length+=1                 #长度+1

删除

    与插入数据元素类似,删除数据元素的算法思路为:

  • 如果删除位置不合适,抛出异常
  • 取出删除元素;
  • 从删除元素位置开始遍历到最后一个元素位置,分别将它们向前移动一个位置
  • 长减1

删除元素(ListDelete)的Python代码实现如下:

    def ListDelete(self,i):
        if i>self.length or i <1:
            raise IndexError(\'Index out of range...\')
        else:
            e=self.data[i-1]
            for j in range(i-1,self.length-1):  #从第i个元素到倒数第二个,
                self.data[j]=self[j+1]          #一次等于后一个元素
            self.data[self.length-1] = None     #最后一个元素等于空
            self.length-=1                      #长度-1
            return e

    以上插入和删除的时间复杂度都是O(n)。

 线性表顺序存储的优点

  • 无须为表示表中元素间的逻辑关系而增加额外的存储空间
  • 可以快速的存取表中任一位置的元素

缺点

  • 插入和删除操作需要移动大量的元素
  • 当线性表长度变化较大时,难以确定存储空间的容量
  • 造成存储空间的“碎片”

线性表顺序存储的操作合集

class SqList(object):
    def __init__(self,size=20):  #默认生成20个对象的线性表
        self.data=list(i for i in range(size))  #数据
        self.maxsize=size   #最大长度
        self.length=0       #当前长度
        
    def ListEmpty(self):
        return self.length==0
    
    def ClearList(self):
        for i in range(self.length):self.data[i]=None
        self.length=0
        
    def GetElem(self,i):   #Python没有指针,所以用返回的形式把值赋给e
        if i>self.length or i < 1:
            raise IndexError(\'Index is out of range...\')
        else:
            return self.data[i-1]  
        
    def LoacateElem(self,e):
        for i,item in enumerate(self.data[:self.length]):
            if item==e:return i+1
        return 0
    
    def ListInsert(self, i, e):
        if i>self.length + 1 or i < 1:  #下标不在范围,可以插入最后
            raise IndexError(\'Index is out of range...\')
        elif self.length == self.maxsize:  #线性表已满
            self.data.append(e)   #此处可以动态增加线性表长度,也可以抛出异常
            self.maxsize+=1
            self.length+=1
        elif i <= self.length+1:
            for j in range(i-1,self.length)[::-1]: #第i到length个元素从后往前  
                self.data[j+1]=self.data[j]        #下标依次后移
            self.data[i-1]=e               #第i个元素等于e
            self.length+=1                 #长度+1
            
    def ListDelete(self,i):
        if i>self.length or i<1 :
            raise IndexError(\'Index is out of range...\')
        else:
            e=self.data[i-1]
            for j in range(i-1,self.length-1):  #从第i个元素到倒数第二个,
                self.data[j]=self.data[j+1]          #一次等于后一个元素
            self.data[self.length-1] = None     #最后一个元素等于空
            self.length-=1                      #长度-1
            return e
    
    def ListLength(self):
        return self.length
    
    def ListShow(self):
        print self.data[:self.length]
        
    def ListCreate(self,l):
        for i,e in enumerate(l):
            self.ListInsert(self.length+1, e)
            
    def Union(self,lb):
        for i in range(1,lb.ListLength()+1):   #循环b列表
            e=lb.GetElem(i)                #取出第i个元素
            if self.LoacateElem(e)==0:     #如果该元素不在a中
                self.ListInsert(self.length+1, e)   #将e插入a
            
if __name__==\'__main__\':
    la=SqList()
    lb=SqList()
    print la.ListEmpty()
    la.ListCreate(range(0,20,2))
    la.ListShow()
    lb.ListCreate(range(1,20,3))
    lb.ListShow()
    print la.ListEmpty()
    print la.GetElem(4)
    print la.LoacateElem(1)
    la.ListInsert(5,15)
    la.ListShow()
    print la.ListLength()
    la.ListDelete(4)
    la.ListShow()
    la.Union(lb)
    la.ListShow()
    la.ClearList()
    la.ListShow()
View Code

以上是关于[读书笔记]-大话数据结构-3-线性表-线性表的顺序存储的主要内容,如果未能解决你的问题,请参考以下文章

大话数据结构读书笔记系列线性表

[读书笔记]-大话数据结构-3-线性表-静态链表循环链表和双向链表

大话数据结构读书笔记

《大话数据结构》笔记--线性表的顺序存储结构

学习总结《大话数据结构》- 第3章-线性表

大话数据结构-2