美文网首页
Datawhale编程集训第二天

Datawhale编程集训第二天

作者: dzpyc | 来源:发表于2018-12-19 19:09 被阅读0次

一、单链表

1.链表定义

链表(linked list)是由一组被称为结点的数据元素组成的数据结构,每个结点都包含结点本身的信息和指向下一个结点的地址。由于每个结点都包含了可以链接起来的地址信息,所以用一个变量就能够访问整个结点序列。也就是说,结点包含两部分信息:一部分用于存储数据元素的值,称为信息域;另一部分用于存储下一个数据元素地址的指针,称为指针域。链表中的第一个结点的地址存储在一个单独的结点中,称为头结点或首结点。链表中的最后一个结点没有后继元素,其指针域为空。

2.单链表的结构

单链表
单链表的插入和删除示意图:

3.Python 实现链表

定义节点类Node:

class Node():
  __slots__=['_item','_next'] # 限定Node实例的属性
  def __init__(self,item):
    self._item = item
    self._next = None # Node的指针部分默认指向None
  def getItem(self):
    return self._item
  def getNext(self):
    return self._next
  def setItem(self,newitem):
    self._item = newitem
  def setNext(self,newnext):
    self._next=newnext

定义单链表:

class SingleLinkedList():
  def __init__(self):
    self._head = None #初始化链表为空 始终指向链表的头部
    self._size = 0 # 链表大小
 
  # 返回链表的大小
  def size(self):
    current = self._head
    count = 0
    while current != None:
      count += 1
      current = current.getNext()
    return count
 
  # 遍历链表
  def travel(self):
    current = self._head
    while current != None:
      print(current.getItem())
      current = current.getNext()
  
  # 检查链表是否为空
  def isEmpty(self):
    return self._head == None
 
  # 在链表前端添加元素
  def add(self,item):
    temp = Node(item) # 创建新的节点
    temp.setNext(self._head) # 新创建的next指针指向_head
    self._head = temp # _head指向新创建的指针
 
  # 在链表尾部添加元素
  def append(self,item):
    temp = Node(item)
    if self.isEmpty():
      self._head = temp # 若为空表就直接插入
    else:
      current = self._head
      while current.getNext() != None:
        current = current.getNext() # 遍历列表
      current.setNext(temp) # 此时current为链表最后的元素,在末尾插入
 
  # 检索元素是否在链表中
  def search(self,item):
    current = self._head
    founditem = False
    while current != None and not founditem:
      if current.getItem() == item:
        founditem = True
      else:
        current = current.getNext()
    return founditem
 
  # 索引元素在表中的位置
  def index(self,item):
    current = self._head
    count = 0
    found = None
    while current != None and not found:
      count += 1
      if current.getItem() == item:
        found = True
      else:
        current = current.getNext()
    if found:
      return count
    else:
      return -1 # 返回-1表示不存在
 
  # 删除表中的某项元素
  def remove(self,item):
    current = self._head
    pre = None
    while current!=None:
      if current.getItem() == item:
        if not pre:
          self._head = current.getNext()
        else:
          pre.setNext(current.getNext())
        break
      else:
        pre = current
        current = current.getNext()
 
  # 在链表任意位置插入元素
  def insert(self,pos,item):
    if pos <= 1:
      self.add(item)
    elif pos > self.size():
      self.append(item)
    else:
      temp = Node(item)
      count = 1
      pre = None
      current = self._head
      while count < pos:
        count += 1
        pre = current
        current = current.getNext()
      pre.setNext(temp)
      temp.setNext(current)

二、leetcode编程练习

第一题:142 环形链表II

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos-1,则在该链表中没有环。

说明:不允许修改给定的链表。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:tail connects to node index 1
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:
输入:head = [1,2], pos = 0
输出:tail connects to node index 0
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入:head = [1], pos = -1
输出:no cycle
解释:链表中没有环。

思路一:
首先,判断是否为环形链表,使用追赶的方法,设定两个指针slow、fast,从头指针开始,每次分别前进1步、2步。如存在环,则两者相遇;如不存在环,fast遇到NULL退出。
然后对于环起始位置有:快慢指针相遇点到环入口的距离 = 链表起始点到环入口的距离。

代码:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if head == None or head.next == None:
            return None
        slow = head
        fast = head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            if fast == slow:
                break
        if slow == fast:
            fast = head
            while fast != slow:
                slow = slow.next
                fast = fast.next
            return slow
        return None

运行结果:


思路二:
采用hashset的方法,当散列表遇到重复元素时,就相当于定位在了环开始的位置,即环的起始位节点,也就是返回链表开始入环的第一个节点。

代码:

class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        hashset = set()
        while head :
            #如果head不在set里,就添加进去
            if head not in hashset:
                hashset.add(head)
            #如果在set内,说明重复了,直接返回head
            else:
                return head
            head = head.next
        return None    

第二题:206 反转链表

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

思路:循环实现

代码:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """

        if head is None: 
            return None
        temp = head
        cur = None
        pre = None
        while temp:
            cur = temp.next
            temp.next = pre
            pre = temp
            temp = cur
        return pre

运行结果:


参考内容:
https://www.jb51.net/article/123464.htm
https://www.cnblogs.com/yupeng/p/3413763.html
http://blog.51cto.com/9291927/2063164
http://www.cnblogs.com/king-ding/p/pythonchaintable.html

相关文章

网友评论

      本文标题:Datawhale编程集训第二天

      本文链接:https://www.haomeiwen.com/subject/vlijkqtx.html