常见数据结构与算法-数组与链表(python3 代码)

 

常见数据结构有线性表(数组与链表),栈与队列,树与二叉树,图。

1.线性表

线性表是最常用且最简单的一种数据结构,它是数据元素的有限序列。线性表有两种实现形式,第一种是用一组连续的存储单元依次存储线性表的数据元素,使用数组存储线性表的元素,也就是python里面的List。第二种就是用一组任意的存储单元存储线性表的数据元素,使用链表存储线性表的元素,这里存储单元可以连续,也可以不连续,也就是python里面的LinkedList。

http://www.runoob.com/python3/python3-list.html 这个链接里面有python3 list的常见操作。

上面是数组,下面是链表。

# LinkList单链表


class Node(object):
    def __init__(self, data, next):
        self.data = data
        self.next = next


class LinkList(object):
    def __init__(self):
        self.root = None

    # 给单链表添加元素节点
    def addNode(self, data):
        if self.root is None:
            self.root = Node(data=data, next=None)
            return self.root
        else:
            # 有头结点,则需要遍历到尾部节点,进行链表增加操作
            curr = self.root
            while curr.next is not None:
                curr = curr.next
            curr.next = Node(data=data, next=None)
            return self.root

    # 在链表的尾部添加新节点,底层调用addNode方法即可
    def append(self, value):
        self.addNode(data=value)

    # 在链表首部添加节点
    def preAppend(self, value):
        if self.root is None:
            self.root = Node(value, None)
        else:
            newRoot = Node(value, None)
            # 更新root索引
            newRoot.next = self.root
            self.root = newRoot

    # 在链表的指定位置添加节点
    def insert(self, index, value):
        if self.root is None:
            return
        if index<= 0 or index >self.size():
            print('index %d 非法,应该审视一下您的插入节点在整个链表的位置!')
            return
        elif index == 1:
            # 如果index == 1,则在链表首部添加即可
            self.preAppend(value)
        elif index == self.size() + 1:
            # 如果index正好比当前链表长度大一,则添加在尾部即可
            self.append(value)
        else:
            # 如此,在链表中部添加新节点,直接进行添加即可。需要使用计数器来维护插入未知
            counter = 2
            pre = self.root
            cursor = self.root.next
            while cursor is not None:
                if counter == index:
                    temp = Node(value, None)
                    pre.next = temp
                    temp.next = cursor
                    break
                else:
                    counter += 1
                    pre = cursor
                    cursor = cursor.next

    # 删除指定位置上的节点
    def delNode(self, index):
        if self.root is None:
            return
        if index <= 0 or index > self.size():
            print('index %d 非法,应该审视一下您的删除节点在整个链表的位置!')
            return
        # 对第一个位置需要小心处理
        if index == 1:
            self.root = self.root.next
        else:
            pre = self.root
            cursor = pre.next
            counter = 2
            while cursor is not None:
                if index == counter:
                    print('can be here!')
                    pre.next = cursor.next
                    break
                else:
                    pre = cursor
                    cursor = cursor.next
                    counter += 1

    # 删除值为value的链表节点元素
    def delValue(self, value):
        if self.root is None:
            return
        # 对第一个位置需要小心处理
        if self.root.data == value:
            self.root = self.root.next
        else:
            pre = self.root
            cursor = pre.next
            while cursor is not None:
                if cursor.data == value:
                    pre.next = cursor.next
                    # 千万记得更新这个节点,否则会出现死循环。
                    cursor = cursor.next
                    continue
                else:
                    pre = cursor
                    cursor = cursor.next

    # 判断链表是否为空
    def isEmpty(self):
        if self.root is None or self.size() == 0:
            return True
        else:
            return False

    # 删除链表及其内部所有元素
    def truncate(self):
        if self.root is None or self.size() == 0:
            return
        else:
            cursor = self.root
            while cursor is not None:
                cursor.data = None
                cursor = cursor.next
            self.root = None
            cursor = None

    # 获取指定位置的节点的值
    def getValue(self, index):
        if self.root is None or self.size() == 0:
            print('当前链表为空!')
            return None
        if index <= 0 or index > self.size():
            print('index %d不合法!'%index)
            return None
        else:
            counter = 1
            cursor = self.root
            while cursor is not None:
                if index == counter:
                    return cursor.data
                else:
                    counter += 1
                    cursor = cursor.next

    # 获取链表尾部的值,且不删除该尾部节点
    def peek(self):
        return self.getValue(self.size())

    # 获取链表尾部节点的值,并删除该尾部节点
    def pop(self):
        if self.root is None or self.size() == 0:
            print('当前链表已经为空!')
            return None
        elif self.size() == 1:
            top = self.root.data
            self.root = None
            return top
        else:
            pre = self.root
            cursor = pre.next
            while cursor.next is not None:
                pre = cursor
                cursor = cursor.next
            top = cursor.data
            cursor = None
            pre.next = None
            return top

    # 单链表逆序实现
    def reverse(self):
        if self.root is None or self.size() == 1:
            return
        else:
            pre = None
            cursor = self.root
            while cursor is not None:
                # print('逆序操作')
                post = cursor.next
                cursor.next = pre
                pre = cursor
                cursor = post
            # 千万不要忘记把逆序后的头结点赋值给root,否则无法正确显示
            self.root = pre

    # 删除链表中的重复元素
    def delDuplecate(self):
        # 使用一个map来存放即可,类似于变形的'桶排序'
        dic = {}
        if self.root is None:
            return
        if self.size() == 1:
            return
        pre = self.root
        cursor = pre.next
        # 为字典赋值
        temp = self.root
        while temp is not None:
            dic[str(temp.data)] = 0
            temp = temp.next
        temp = None
        # 开始实施删除重复元素的操作
        while cursor is not None:
            if dic[str(cursor.data)] == 1:
                pre.next = cursor.next
                cursor = cursor.next
            else:
                dic[str(cursor.data)] += 1
                pre = cursor
                cursor = cursor.next

    # 修改指定位置节点的值
    def updateNode(self, index, value):
        if self.root is None:
            return
        if index < 0 or index > self.size():
            return
        if index == 1:
            self.root.data = value
            return
        else:
            counter = 2
            cursor = self.root.next
            while cursor is not None:
                if counter == index:
                    cursor.data = value
                    break
                cursor = cursor.next
                counter += 1

    # 获取单链表的大小
    def size(self):
        counter = 0
        if self.root is None:
            return counter
        else:
            cursor = self.root
            while cursor is not None:
                counter += 1
                cursor = cursor.next
            return counter

    # 打印链表自身元素
    def print(self):
        if self.root is None:
            return
        else:
            cursor = self.root
            while cursor is not None:
                print(cursor.data, end='\t')
                cursor = cursor.next
            print()

if __name__ == '__main__':
    # 创建一个链表对象
    array = LinkList()
    # 判断当前链表是否为空
    print("链表为空{}".format(array.isEmpty()))
    # 判断当前链表是否为空
    array.addNode(1)
    print("链表为空{}".format(array.isEmpty()))
    # 添加一些节点,方便操作
    array.addNode(2)
    array.addNode(3)
    array.addNode(4)
    array.addNode(6)
    array.addNode(5)
    array.addNode(6)
    array.addNode(7)
    array.addNode(3)
    # 打印当前链表所有值
    print('打印当前链表所有值')
    array.print()
    # 测试对链表求size的操作
    print("链表的size: " + str(array.size()))
    # 测试指定位置节点值的获取
    print('测试指定位置节点值的获取')
    print(array.getValue(1))
    print(array.getValue(array.size()))
    print(array.getValue(7))
    # 测试删除链表中指定值,可重复性删除
    print('测试删除链表中指定值,可重复性删除')
    array.delNode(4)
    array.print()
    array.delNode(3)
    array.print()
    # 去除链表中的重复元素
    print('去除链表中的重复元素')
    array.delDuplecate()
    array.print()
    # 指定位置的链表元素的更新测试
    print('指定位置的链表元素的更新测试')
    array.updateNode(6, 99)
    array.print()
    # 测试在链表首部添加节点
    print('测试在链表首部添加节点')
    array.preAppend(77)
    array.preAppend(108)
    array.print()
    # 测试在链表尾部添加节点
    print('测试在链表尾部添加节点')
    array.append(99)
    array.append(100)
    array.print()
    # 测试指定下标的插入操作
    print('测试指定下标的插入操作')
    array.insert(1, 10010)
    array.insert(3, 333)
    array.insert(array.size(), 99999)
    array.print()
    # 测试peek 操作
    print('测试peek 操作')
    print(array.peek())
    array.print()
    # 测试pop 操作
    print('测试pop 操作')
    print(array.pop())
    array.print()
    # 测试单链表的逆序输出
    print('测试单链表的逆序输出')
    array.reverse()
    array.print()
    # 测试链表的truncate操作
    print('测试链表的truncate操作')
    array.truncate()
    array.print()

 下面是单向循环链表,至于双向链表和双向循环链表以后有时间再补上吧。

# sinCycLinkedList 单向循环链表
class Node(object):
  """节点"""
  def __init__(self, item):
    self.item = item
    self.next = None

class SinCycLinkedlist(object):
  """单向循环链表"""
  def __init__(self):
    self._head = None

  def is_empty(self):
    """判断链表是否为空"""
    return self._head == None

  def length(self):
    """返回链表的长度"""
    # 如果链表为空,返回长度0
    if self.is_empty():
      return 0
    count = 1
    cur = self._head
    while cur.next != self._head:
      count += 1
      cur = cur.next
    return count

  def travel(self):
    """遍历链表"""
    if self.is_empty():
      return
    cur = self._head
    print(cur.item,)
    while cur.next != self._head:
      cur = cur.next
      print(cur.item,)
    print("")

  def add(self, item):
    """头部添加节点"""
    node = Node(item)
    if self.is_empty():
      self._head = node
      node.next = self._head
    else:
      #添加的节点指向_head
      node.next = self._head
      # 移到链表尾部,将尾部节点的next指向node
      cur = self._head
      while cur.next != self._head:
        cur = cur.next
      cur.next = node
      #_head指向添加node的
      self._head = node

  def append(self, item):
    """尾部添加节点"""
    node = Node(item)
    if self.is_empty():
      self._head = node
      node.next = self._head
    else:
      # 移到链表尾部
      cur = self._head
      while cur.next != self._head:
        cur = cur.next
      # 将尾节点指向node
      cur.next = node
      # 将node指向头节点_head
      node.next = self._head

  def insert(self, pos, item):
    """在指定位置添加节点"""
    if pos <= 0:
      self.add(item)
    elif pos > (self.length()-1):
      self.append(item)
    else:
      node = Node(item)
      cur = self._head
      count = 0
      # 移动到指定位置的前一个位置
      while count < (pos-1):
        count += 1
        cur = cur.next
      node.next = cur.next
      cur.next = node

  def remove(self, item):
    """删除一个节点"""
    # 若链表为空,则直接返回
    if self.is_empty():
      return
    # 将cur指向头节点
    cur = self._head
    pre = None
    # 若头节点的元素就是要查找的元素item
    if cur.item == item:
      # 如果链表不止一个节点
      if cur.next != self._head:
        # 先找到尾节点,将尾节点的next指向第二个节点
        while cur.next != self._head:
          cur = cur.next
        # cur指向了尾节点
        cur.next = self._head.next
        self._head = self._head.next
      else:
        # 链表只有一个节点
        self._head = None
    else:
      pre = self._head
      # 第一个节点不是要删除的
      while cur.next != self._head:
        # 找到了要删除的元素
        if cur.item == item:
          # 删除
          pre.next = cur.next
          return
        else:
          pre = cur
          cur = cur.next
      # cur 指向尾节点
      if cur.item == item:
        # 尾部删除
        pre.next = cur.next

  def search(self, item):
    """查找节点是否存在"""
    if self.is_empty():
      return False
    cur = self._head
    if cur.item == item:
      return True
    while cur.next != self._head:
      cur = cur.next
      if cur.item == item:
        return True
    return False

if __name__ == "__main__":
  ll = SinCycLinkedlist()
  ll.add(1)
  ll.add(2)
  ll.append(3)
  ll.insert(2, 4)
  ll.insert(4, 5)
  ll.insert(0, 6)
  print("length:",ll.length())
  ll.travel()
  print(ll.search(3))
  print(ll.search(7))
  ll.remove(1)
  print("length:",ll.length())
  ll.travel()

下一篇我会具体讲一讲数据结构中的栈与队列。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值