zoukankan      html  css  js  c++  java
  • [读书笔记]-大话数据结构-3-线性表(二)-线性表的链式存储

    线性表链式存储结构

        为了解决线性表插入、删除操作复杂和空间大小不灵活等缺点, 可以用链式存储结构表示线性表。链式存储结构的定义为:为了表示每个数据元素ai与其直接后继数据元素ai+1之间的逻辑关系,对数据元素ai来说,除了存储其本身的信息之外,还需要存储一个指示其后继的信息(即直接后继的存储位置)。我们把存储数据元素信息的域称为数据域,把存储直接后继位置的域称作为指针。这两部分信息组成数据元素ai的存储映像,称为节点(Node).

        n个节点链接成一个链表,即线性表(a1,a2,...an)的链式存储结构。因为该链表每个节点只包含一个指针域,也叫做单链表。如下图:

        我们把链表中第一个节点存储位置叫做头指针,整个链表的存取都必须从头指针开始。最后一个节点的指针一般为空。有时,我们会在单链表的第一个节点前辅设一个节点,称为头结点。头结点的数据域可以不存储任何信息或者链表长度等附加信息。如下图

     

     头指针与头结点的异同

    链式存储Python代码实现

    class Node(object):
        def __init__(self,data=None):  #生成数据节点
            self.data=data
            self.next=None             #指针默认指向空
            
    class LinkList(object):
        def __init__(self):      #生成一个链表,无头结点,默认指向空  
            self.head=None   

    单链表的读取

        单链表中第i个数据的算法思路:

    • 声明一个节点p,指向链表的第一个节点,初始化j从1 开始;
    • 当j<i时,就遍历链表,让p的指针向后移动,不断指向下一节点,j累加1;
    • 若链表末尾p为空,则说明第i个元素不存在;
    • 否则查找成功,返回节点p的数据。

    Python实现代码:

        def GetElem(self,i):   
            p=self.head    #p指向链表的头
            j=1            #初始下标为1
            while p!=None and j<i:   #下标小于i或者p不到链表尾部(p=None)时,资讯
                j+=1              #下标加1
                p=p.next          #节点指向下一个
            if p==None or j>i: raise IndexError('not exit')   #第i个元素不存在
            return p.data    #返回第i个元素的值

        这个算法的时间复杂度为O(n)。算法的核心思想是“工作指针后移”

    单链表的插入与删除

    插入

        要向单链表中插入数据(ai与ai+1之间插入),需要先断开ai与ai+1之间的指针,将新节点s指向ai+1,并用ai指向s,如下图所示三种情况:

        单链表第i个数据插入节点的算法思路:

    • 声明一个指针p,指向链表的头,初始化j从1开始
    • 当j<i时遍历链表,让p遍历链表,指向下一个节点,并且j累加1;
    • 如果p到达链表的尾部,说明i不存在;
    • 否则查找成功,生成一个节点s,将数据e赋值给s;
    • 在位置i后插入链表,插入的标准语句为:s.next=p.next      p.next=s
    • 返回成功

     Python实现代码

        def ListInsert(self, i, e):
            p=self.head           
            j=1
            while p!=None and j<i:   
                j+=1
                p=p.next
            if p==None or j>i: raise IndexError('not exit')
            s=Node(e)            #生成新节点
            s.next=p.next       #新节点指向p的下一个元素
            p.next=s            #p指向s
            return True         #返回成功

    删除

         删除节点实际上是将删除节点(ai)的前一个节点(ai-1)的指针绕过ai,直接指向ai+1,如下图所示

     

    单链表第i个数据删除节点的算法思路:

    • 声明一个节点p指向链表的头,初始化q(p的前一个节点)指向空,j从1开始;
    • 当j<i时,遍历链表,让p不断指向下一个节点,q指向p, j累加1
    • 若到达链表尾部(p为空),说明i不存在
    • 否则查找成功,将p的前一个节点q指向p.next
    • 将p的值返回

    Python实现代码

        def ListDelete(self,i):
            p=self.head       #工作节点
            q=None            #p的前一个节点
            j=1
            while p!=None and j<i:  #遍历寻找节点i
                j+=1
                q=p
                p=p.next
            if p==None or j>i:raise IndexError('not exit')
            if q==None: self.head=p.next   #当q指向空时,头指针指向p.next
            else: q.next=p.next          #上一个节点指向p.next,即删除p
            return p.data     #返回p的值

        插入和删除的时间复杂度都是O(n),但是需要同时删除多个数据时,链表存储不用再多遍历一遍,所以,对于插入或者删除数据越频繁的操作,单链表的效率优势越明显。

    单链表的整表创建

     单链表整表创建的思路:

    • 对待插入数据执行循环:
      • 用数据e生成一个节点p
      • 用p指向链表的头
      • 链表的头重新指向p
        def ListCreate(self,l):
            l.reverse()
            for e in l:         #从最后一个元素到第一个元素
                p=Node(e)            #生成一个新节点
                p.next=self.head     #这个及诶单指向链表头
                self.head=p          #链表头指向这个节点

         上面的方法是在头结点之前一次插入数据,也可以在链表尾部依次插入数据:

    • 对待插入数据执行循环:
      • 用数据e生成一个节点p
      • 如果头为空,头指向p,否则尾节点指向p
      • 让p等于尾节点
        def ListCreateTail(self,l):
            self.head=None
            q=None
            for e in l:         #从第一个到最后一个元素
                p=Node(e)       #新生成一个节点
                if self.head==None:   #如果头结点为空
                    self.head=p       #头节点指向先生存的节点
                else:q.next=p         #否则q指向新节点
                q=p                   #q等于尾节点

    单链表结构与顺序存储结构优缺点

        若线性表需要频繁查找,很少进行插入和删除操作时,宜采用顺序存储结构。若需要频繁插入和删除时,宜采用单链表结构。

        若线性表的元素个数变化较大或者根本不知道有多大时,最好用单链表结构,如果事先知道线性表的大致长度,用顺序存储结构较好。

     代码合集

    #encoding=UTF-8
    class Node(object):
        def __init__(self,data=None):  #生成数据节点
            self.data=data
            self.next=None             #指针默认指向空
            
    class LinkList(object):
        def __init__(self):      #生成一个链表,无头结点,默认指向空  
            self.head=None       
            
        def ListEmpty(self):
            return self.head==None
        
        def ClearList(self):
            self.head=None
            
        def GetElem(self,i):   
            p=self.head    #p指向链表的头
            j=1            #初始下标为1
            while p!=None and j<i:   #下标小于i或者p不到链表尾部(p=None)时,资讯
                j+=1              #下标加1
                p=p.next          #节点指向下一个
            if p==None or j>i: raise IndexError('not exit')   #第i个元素不存在
            return p.data    #返回第i个元素的值
            
        def LoacateElem(self,e):
            p=self.head
            i=0
            while p!=None:
                i+=1
                if p.data==e:return i
                p=p.next
            return -1
        
        def ListInsert(self, i, e):
            p=self.head           
            j=1
            while p!=None and j<i:   
                j+=1
                p=p.next
            if p==None or j>i: raise IndexError('not exit')
            s=Node(e)            #生成新节点
            s.next=p.next       #新节点指向p的下一个元素
            p.next=s            #p指向s
            return True         #返回成功
               
        def ListDelete(self,i):
            p=self.head       #工作节点
            q=None            #p的前一个节点
            j=1
            while p!=None and j<i:  #遍历寻找节点i
                j+=1
                q=p
                p=p.next
            if p==None or j>i:raise IndexError('not exit')
            if q==None: self.head=p.next   #当q指向空时,头指针指向p.next
            else: q.next=p.next          #上一个节点指向p.next,即删除p
            return p.data     #返回p的值
            
        def ListLength(self):
            cnt=0
            p=self.head
            while p!=None:
                cnt+=1
                p=p.next
            return cnt
        
        def ListShow(self):
            p=self.head
            q=self.head
            while p!=None:
                print p.data,
                p=p.next
            print ''
            
        def ListCreate(self,l):
            self.head=None
            l.reverse()
            for e in l:         #从最后一个元素到第一个元素
                p=Node(e)            #生成一个新节点
                p.next=self.head     #这个及诶单指向链表头
                self.head=p          #链表头指向这个节点
    
        def ListCreateTail(self,l):
            self.head=None
            q=None
            for e in l:         #从第一个到最后一个元素
                p=Node(e)       #新生成一个节点
                if self.head==None:   #如果头结点为空
                    self.head=p       #头节点指向先生存的节点
                else:q.next=p         #否则q指向新节点
                q=p                   #q等于尾节点
                
        def Union(self,lb):
            p=lb.head
            while p!=None:
                e=p.data
                if self.LoacateElem(e)==-1:  #如果p.data不在la中
                    q=Node(e)
                    q.next=self.head
                    self.head=q
                p=p.next
                
    if __name__=='__main__':
        la=LinkList()
        lb=LinkList()
        print la.ListEmpty()
        la.ListCreateTail(range(0,20,2))
        la.ListShow()
        lb.ListCreate(range(1,20,3))
        lb.ListShow()
        
        print la.ListEmpty()
        print la.GetElem(7)
        
        print la.LoacateElem(8)
        la.ListInsert(5,15)
        la.ListShow()
        
        print la.ListLength()
        #print la.ListDelete(1)
        la.ListShow()
        
        la.Union(lb)
        la.ListShow()
        la.ClearList()
        la.ListShow()
        
    View Code
  • 相关阅读:
    nginx能访问html静态文件但无法访问php文件
    LeetCode "498. Diagonal Traverse"
    LeetCode "Teemo Attacking"
    LeetCode "501. Find Mode in Binary Search Tree"
    LeetCode "483. Smallest Good Base" !!
    LeetCode "467. Unique Substrings in Wraparound String" !!
    LeetCode "437. Path Sum III"
    LeetCode "454. 4Sum II"
    LeetCode "445. Add Two Numbers II"
    LeetCode "486. Predict the Winner" !!
  • 原文地址:https://www.cnblogs.com/zhaoxy/p/7728122.html
Copyright © 2011-2022 走看看