python中的数据结构-链表

一.什么是链表

链表是由一系列节点构成,每个节点由一个值域和指针域构成,值域中存储着用户数据,指针域中存储这指向下一个节点的指针.根据结构的不同,链表可以分为单向链表、单向循环链表、双向链表、双向循环链表等。单向链表的结构如下图所示:

head 节点永远指向第一个节点, tail节点永远指向最后一个节点,节点中最后一个指针指向的是None 值,链表本质上就是由指针链接起来的一系列值.

二.为什么使用链表

我们经常拿链表和数组作比较,实际上数组是一组固定长度的序列,链表可以动态地分配元素,下面我们了解一下使用链表的优缺点

  优点:

  链表节省内存.它只针对待存储数据分配所需内存,在创建数组时,必须预先设置数组的大小,然后再添加数据,这可能会浪费内存。

  缺点

  查找或访问特定节点的时间是O(n). 在链接列表中查找值时,必须从头开始,并一次检查一每个元素以找到要查找的值。 如果链接列表的长度为n,则最多花费O(n)。

  而很多语言中在数组中查找特定的元素则需花费O(1)时间

三.python 实现链表

      1)节点

  python 用类来实现链表的数据结构,节点(Node)是链表中存储数据的地方,除了数据之外节点中还有指向下一个节点的指针。节点是实现链表的基本模块,下边用python代码来实现一个节点类

 class Node:
     def _init_(self,val):
       self.val=val
       self.next_node = None       #the pointer initially points to pointer

     def get_val(self):
       return self.val            #returns the stored data

     def get_next(self):
       return self.next_node       #returns the next node (the node to which the object node points)

     def set_val(self, new_val):
        self.val = new_val       # reset the vaue to a new value
     def set_next(self, new_next):
        self.next_node = new_next  # reset the pointer to a new node

此节点类只有一个构建函数,接收一个数据参数,其中next表示指针域的指针,接下来我们用如下方式去初始化一个链表:

node1 = Node(4)
node2 = Node(21)
node3 = Node(90)
node1.next = node2  #4->21
node2.next = node3  #21->90
# the entire linked list now looks like: 4->21->90

  借助上边的节点类我们可以很方便的构造出链表

  2)链表

  单向链表的实现包含了如下几个方法:

  append(): 向链表中增加一个元素

insert(): 向链表中插入一个新节点

  size(): 返回链表的长度

  search(): 在链表中查找数据项是否存在

  delete(): 删除链表中的数据项

empty(): 判断链表是否为空

iterate(): 遍历链表

链表的头结点:

  首先构建链表的头结点也就是链表中的第一个节点,当链表在初始化时不包含任何节点,所以它的头节点设置为空  

class LinkedList:
    def _init_(self):
      self.head = None
      self.tail = None

  实例化代码如下

linklist = LinkedList()

append()

append方法表示增加元素到链表,这和insert方法不同,前者使新增加的元素成为链表中第一个节点,而后者是根据索引值来判断插入到链表的哪个位置。代码如下:

  def append(self, val):
     new_node = Node(val)
     if self.head is None:
      self.head = new_node
      self.tail = new_node
     else:
      self.tail.set_next(new_node)
      self.tail = new_node

        insert()

        该方法获得一个数据,对于给定数据初始化一个节点,并将该节点添加到链表中去。最简单的实现方法是把它插入到链表头处,并让新节点指向原来的头结点,该方法二时间复杂度为O(1):

def insert(self, val):
    new_node = Node(val)
    new_node.set_next(self.head)
    self.head = new_node

  如果要在特定位置插入节点要提前找到这个位置,在链表中只能采用遍历的方法,时间复杂度为O(n). 同时我们还要考虑额外的三种情况:

  1)空链表时

  2)插入位置超出链表节点的长度时 

  3)插入位置是链表的最后一个节点时,需要移动tail

    def insert(self, index, val):
          current_node = self.head
          current_node_index = 9
          if current_node is None:
            raise Exception(‘This is an empty linked list‘)
          while current_node_index < index-1:
            current_node = current_node.next
            if current_node is None:
              raise Exception(‘exceed the length of the list‘)
            current_node_index += 1
            node = Node(val)
            node.next = current_node.next
            current_node.next = node
            if node.next is None:
              self.tail = node
  

    size()

               返回链表长度的方法非常简单,统计链表中的节点数目直到找不到更多的节点为止返回遍历的节点的数目。该方法从表头开始,直到最后一个节点的next指针指向None时链表遍历完成。同时用计数器记录下已经遍历的节点的数目

 def size(self):
     current_node = self.head
     count = 0
     if current_node is None:
        return ‘This is an empty linked list‘
     while current_node:
        count += 1
        current_node = current_node.get_next()
      return count

search()

search()与size() 方法很相似,但是除了要遍历整个链表,search()还要检查他遍历的每一个节点是否包含要查找的数据,并返回含有该数据的节点。如果该方法遍历整个链表没有找到包含该数据的节点,它将会抛出一个异常并通知用户该数据不在链表中   

 def search(self, val):
     current_node = self.head
     found = false
     while current_node and found is false:
       if current_node.get_val == val:
         found = True
       else:
         current_node = current_node.get_next()
     if current_node is None:
       raise ValueError(‘Data not in list‘)

             delete()

             delete()与search()方法非常相似,它采用与serch()相同的方法遍历整个链表,但除了要记录下当前节点之外, delete()还要记住当前节点的上一个节点,当deleta()方法遍历到要删除的节点时,它会将待删除节点的上一个节点的指针指向待删除节点的下一个节点,此时链表中将没有节点指向待删除节点。该方法的时间复杂度为O(n),因为在最坏情况下该方法要访问链表中的所有节点。同时我们还需要考虑如下几种情况:

    1) 空链表,直接抛出异常

2) 删除第一个节点时,移动head到删除节点的next指针指向的对象

3) 链表只有一个节点时,把head与tail都指向None即可

4) 删除最后一个节点时,需要移动tail到上一个节点

5) 遍历链表时要判断给定的索引是否大于链表的长度,如果大于则抛出异常信息 

   def delete(self, val):
     curent_node = self.head
     previous = None
     found = False
     while current_node and found is False:
       if current_node.get_val() == val:
         found = True
       else:
         previous = current_node
         current_node = current_node.get_next()
     if current_node is None:
       raise ValueError(‘Data not in list‘)
     if self.head is self.tail:          # when there is only one node in the list
       self.head = None
       self.tail = None
     if current_node is None:            #when delete the tail node  
       self.tail = current_node
     if previous is None:               #when delete the first node
       self.head = current_node.get_next()
     else :
       previous.set_next(current.get_next())
 

             empty()

        判断链表是否为空就看他的头指针是否为空

   def empty(self):
        return return self.head is None

    iterate()
             
遍历链表从头结点开始,直到节点的指针指向None为止

    def iterate(self):
      if not self.head:       # if the linked list is empty
        return
      current_node = self.head
      yield current_node.val
      while current_node.next
        current_node = current_node.next
        yield current_node.val

完整代码如下

  1 class Node:
  2   def __init__(self,val):
  3     self.val=val
  4     self.next = None #the pointer initially points to pointer
  5   def get_val(self):
  6     return self.val
  7   def get_next(self):
  8     return self.next
  9   def set_val(self, new_val):
 10       self.val = new_val
 11   def set_next(self, new_next):
 12       self.next = new_next
 13
 14 class LinkedList:
 15   def __init__(self):
 16     self.head = None
 17     self.tail = None
 18
 19   def insert(self, index, val):
 20         current_node = self.head
 21         current_node_index = 0
 22         if current_node is None:
 23           raise Exception(‘This is an empty linked list‘)
 24         while current_node_index < index-1:
 25           current_node = current_node.next
 26           if current_node is None:
 27             raise Exception(‘exceed the length of the list‘)
 28           current_node_index += 1
 29         node = Node(val)
 30         node.next = current_node.next
 31         current_node.next = node
 32         if node.next is None:
 33           self.tail = node
 34   def size(self):
 35     current_node = self.head
 36     count = 0
 37     if current_node is None:
 38       return ‘This is an empty linked list‘
 39     while current_node:
 40       count += 1
 41       current_node = current_node.get_next()
 42     return count
 43
 44   def search(self, val):
 45     current_node = self.head
 46     found = False
 47     while current_node and found is False:
 48       if current_node.get_val() == val:
 49         found = True
 50       else:
 51         current_node = current_node.get_next()
 52     if current_node is None:
 53       raise ValueError(‘Data not in list‘)
 54     return found
 55
 56   def delete(self, val):
 57     current_node = self.head
 58     previous = None
 59     found = False
 60     while current_node and found is False:
 61       if current_node.get_val() == val:
 62         found = True
 63       else:
 64         previous = current_node
 65         current_node = current_node.get_next()
 66
 67     if current_node is None:
 68       raise ValueError(‘Data not in list‘)
 69
 70     if self.head is self.tail:
 71       self.head = None
 72       self.tail = None
 73
 74     if current_node is None:
 75       self.tail = current_node
 76
 77     if previous is None:
 78       self.head = current_node.get_next()
 79     else :
 80       previous.set_next(current.get_next())
 81
 82   def iterate(self):
 83     if not self.head:
 84       return
 85     current_node = self.head
 86     yield current_node.val
 87     while current_node.next:
 88       current_node = current_node.next
 89       yield current_node.val
 90
 91   def append(self, val):
 92     new_node = Node(val)
 93     if self.head is None:
 94      self.head = new_node
 95      self.tail = new_node
 96     else:
 97      self.tail.set_next(new_node)
 98      self.tail = new_node
 99   def empty(self):
100     return self.head is None
101
102 if __name__ == ‘__main__‘:
103   linklist = LinkedList()
104   for i in range(50):
105     linklist.append(i)
106   print(linklist.empty())
107   linklist.insert(20,20)
108   linklist.delete(0)
109   for node in linklist.iterate():
110     print(‘node is {0}‘.format(node))
111   print(linklist.size())
112   print(linklist.search(13))
                                                                 

参考链接:

http://zhaochj.github.io/2016/05/12/2016-05-12-%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-%E9%93%BE%E8%A1%A8/

https://www.codefellows.org/blog/implementing-a-singly-linked-list-in-python/

  

原文地址:https://www.cnblogs.com/laozhanghahaha/p/8642333.html

时间: 2024-10-07 11:44:20

python中的数据结构-链表的相关文章

python中的数据结构

1.列表 (1)   建立列表 list('python') ['p', 'y', 't', 'h', 'o', 'n'] (2)列表的常用方法: append   在列表末尾添加元素 >>>l=['a','b','c'] >>>l.append('d') >>>l ['a','b','c','d'] count   统计某个元素在列表中出现的次数 >>>['a','a','b','c'].count('a') 2 extend  扩

python中的单链表实现

引子 数据结构指的是是数据的组织的方式.从单个数据到一维结构(线性表),二维结构(树),三维结构(图),都是组织数据的不同方式. 为什么需要链表? 顺序表的构建需要预先知道数据大小来申请连续的存储空间,而在进行扩充时又需要进行数据的搬迁,所以使用起来并不是很灵活. 链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理. 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是不像顺序表一样连续存储数据,而是在每一个节点(数据存储单元)里存放下一个节点的位置信息(即地址).

Python中的高级数据结构(转)

add by zhj: Python中的高级数据结构 数据结构 数据结构的概念很好理解,就是用来将数据组织在一起的结构.换句话说,数据结构是用来存储一系列关联数据的东西.在Python中有四种内建的数据 结构,分别是List.Tuple.Dictionary以及Set.大部分的应用程序不需要其他类型的数据结构,但若是真需要也有很多高级数据结构可供 选择,例如Collection.Array.Heapq.Bisect.Weakref.Copy以及Pprint.本文将介绍这些数据结构的用法,看 看它

Python中的高级数据结构详解

这篇文章主要介绍了Python中的高级数据结构详解,本文讲解了Collection.Array.Heapq.Bisect.Weakref.Copy以及Pprint这些数据结构的用法,需要的朋友可以参考下 数据结构 数据结构的概念很好理解,就是用来将数据组织在一起的结构.换句话说,数据结构是用来存储一系列关联数据的东西.在Python中有四种内建的数据结构,分别是List.Tuple.Dictionary以及Set.大部分的应用程序不需要其他类型的数据结构,但若是真需要也有很多高级数据结构可供选择

Python中对复杂数据结构排序(类似C中结构体数据结构)

Python中排序主要有两个函数:sorted和列表成员函数sort,两者除了调用方式有些区别外,最显著的区别是sorted会新建一个排序好的列表并返回,而sort是修改原列表并排好序.sorted的原型是: sorted(iterable, cmp=None, key=None, reverse=False) sort的原型是: list.sort(cmp=None, key=None, reverse=False) 其中cmp和key都是函数引用,即可以传入函数名.这两个函数都是对list里

python中的链表

python中的链表(linked list)是一组数据项的集合,其中每个数据项都是一个节点的一部分,每个节点还包含指向下一个节点的链接.链表的数据结构如下图所示 在链表中删除操作可以通过修改指针来实现,如下图所示: 插入则是调整,插入点的前后两个指针的指向关系,如下图所示: 在python中每个变量都是指针,例如: 用内置数据结构(list, dict, tuple等)的嵌套/组合,它们隐式地包含了指向/嵌套关系,如graph[u][v]={w0,w1..}类的成员变量.嵌套类可能包含了指向/

python数据结构链表之单向链表

本文和大家分享的主要是python中单向链表相关内容,一起来看看吧,希望对大家学习python有所帮助. 单向链表 单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域.这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值. . 表元素域elem用来存放具体的数据. . 链接域next用来存放下一个节点的位置(python中的标识) . 变量p指向链表的头节点(首节点)的位置,从p出发能找到表中的任意节点. 节点实现 class 

第二章 python中重要的数据结构(下)

二.元组(tuple):不可变序列 跟list一样,也是一种序列,唯一不同的是,元组元素不能被修改,通常用(, ,)表示元组,也可以不加括号. 1 #创建元组 2 >>> 1,2,3 3 (1, 2, 3) 4 >>> t = (1,2,3) 5 >>> t 6 (1, 2, 3) 7 #创建空元组 8 >>> t1 = () 9 >>> t1 10 () 11 #创建只有一个元素的元组,这里注意必须带上逗号 12

Python学习(一):入门篇:python中的一些数据结构

Python里的一些基本知识点总结 Last Edit 2014/5/2 这里记录的是Python2.7版本的语法特征,部分与Python3.0是不一样的. 一,关于开发环境 在windows下可以直接在官网下载相关的版本,然后默认安装.使用直带的IDLE编辑器. IDLE中两个有用的快捷键: ALT+P:重复历史命令(从最近到最老) ALT+N:   重复历史命令(从最老到最近) IDLE中没有清屏功能. 在cmd中进行: 1,首先要在环境变量的path中添加相关的路径: C:\Python2