数据结构_day03_链表

链表

为什么需要链表

顺序表的构建需要预知数据大小来申请连续的储存空间,而进行扩充时又需要进行数据的搬迁,所以使用起来并不是很灵活。
链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。

链表的定义

链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是不像顺序表一样的连续储存数据,而是在每一个节点(数据储存单元)里存放下一个节点的位置信息(即是地址)。前面的是元素信息,后面是位置信息。
链表

单项链表

单项链表也叫单链表,是链表中最简单的一种形式,他的每个节点包含两个域。

  • 信息域(元素域) : 元素的具体数字多少
  • 一个链接域 : 这个链接指向链表中的下一个节点,而最后一个节点的连接域则指向一个空置None
    单项链表
  • 表元素域elem用来存放具体的数据
  • 连接域next用来存放下一个节点的位置(Python中的标识)
  • 变量p指向链表的头结点(首节点)的位置,从p出发能找到表中的任意结点

结点的代码实现

class Node(object):
    '''单链表的节点'''
    def __init__(self,elem):
        self.elem = elem # elem 是存放数据的元素
        self.next = None # next 是下一个节点的标识

单链表的实现

基本实现

class SingleLinkList(object):
    '''单链表的操作'''
    def __init__(self,node = None):
    # '''这个目的是把头结点连上 是为了方便调用下面的方法'''
        self.__head  = node

    def is_empty(self):
    # '''链表是否为空'''
        return self.__head == None

    def length(self):
    # '''链表长度'''
    # current游标,用来移动遍历节点
        current = self.__head
        # count 记录数量
        count = 0
        while current != None:
            count += 1
            current = current.next
        return count # 移动了几位就是链表长度是多少

    def travel(self):
    # '''遍历整个链表'''
        current = self.__head
        while current != None:
            print(current.elem,end=' ')
            current = current.next

头部添加元素

头部添加元素

    def add(self,item):
    # '''链表头部添加元素 头插法'''
        node = Node(item)
        node.next = self.__head # 将新插入元素的next和__head(此时__head指向第一个元素)连接上
        self.__head = node # 将新元素的节点赋给最前面的__head

尾部添加元素

    def append(self,item): # item不是节点 是具体的一个元素
    # '''链表尾部添加元素 尾插法'''
        node = Node(item)
        if self.is_empty(): # 空列表 直接到头上
            self.__head = node
        else:
            current = self.__head
            while current.next != None:
                current = current.next
            current.next = node

指定位置添加元素

指定位置添加元素

    def insert(self,pos,item):
    # '''指定位置添加元素 pos:从0开始的'''
        if pos <= 0:
            self.add(item)
        elif pos > (self.length() - 1):
            self.append(item)
        else:
            pre = self.__head
            count = 0
            while count <= (pos-1):
                count += 1
                pre = pre.next
            # 循环退出后 pre指向了pos减一的位置
            node = Node(item)
            node.next = pre.next
            pre.next = node

删除节点

删除节点

    def remove(self,item):
    # '''删除节点'''
        current = self.__head
        pre = None
        while current != None:
            if current.elem == item:
                # 先判断此节点是否是头结点
                # 如果是头结点的话
                if current == self.__head:
                    self.__head = current.next
                    break
                else:
                    pre.next = current.next # 核心步骤 删除步骤
                    break
            else:
                pre = current
                current = current.next

查找节点时否存在

    def search(self,item):
    # '''查找节点是否存在'''
        current = self.__head
        while current != None:
            if current.elem == item:
                return True
            else:
                current = current.next
        return False

测试

if __name__ == "__main__": # 这是主函数  就是程序的入口 基本上标准的程序都要写这个main函数
    ll = SingleLinkList()
    print(ll.is_empty())
    print(ll.length())
    print('---')
    print(ll.is_empty())
    print(ll.length())
    print('---')
    ll.append(1)
    ll.append(2)
    ll.append(3)
    ll.append(4)
    ll.append(5)
    ll.append(6)
    ll.add(100) # 添加到头部
    ll.travel()
    print('\n---')
    ll.insert(2,99)
    ll.travel()
    print('\n---')
    ll.insert(-1,12)
    ll.travel()
    print('\n---')
    ll.insert(99,89)
    ll.travel()
    print('\n---')
    ll.remove(12)
    ll.travel()
    print('\n---')
    ll.remove(6)
    ll.travel()
    print('\n---')
    ll.travel()
    print(ll.search(3))

输出:

True
0
---
True
0
---
100 1 2 3 4 5 6 
---
100 1 2 99 3 4 5 6 
---
12 100 1 2 99 3 4 5 6 
---
12 100 1 2 99 3 4 5 6 89 
---
100 1 2 99 3 4 5 6 89 
---
100 1 2 99 3 4 5 89 
---
100 1 2 99 3 4 5 89 True

双向链表

一种更加复杂的链表是双向链表或双面链表。每个节点有两个链接: 一个指向前一个节点,当此节点为第一个节点时,指向空值。
而另一个指向下一个节点,当此节点为最后一个节点,指向空值。
双向链表

实现

class Node(object):
    '''节点'''
    def __init__(self,item):
        self.elem = item
        self.prev = None
        self.next = None

class DoubleLinkList(object):
    '''双链表'''
    def __init__(self,node = None):
    # '''这个目的是把头结点连上 是为了方便调用下面的方法'''
        self.__head  = node

    def is_empty(self):
    # '''链表是否为空'''
        return self.__head is None # 最好用is ==也可以达到效果

    def length(self):
    # '''链表长度'''
    # current游标,用来移动遍历节点
        current = self.__head
        # count 记录数量
        count = 0
        while current != None:
            count += 1
            current = current.next
        return count # 移动了几位就是链表长度是多少

    def travel(self):
    # '''遍历整个链表'''
        current = self.__head
        while current != None:
            print(current.elem,end=' ')
            current = current.next

    def add(self,item):
    # '''链表头部添加元素 头插法'''
        node = Node(item)
        node.next = self.__head # 将新插入元素的next和__head(此时__head指向第一个元素)连接上
        self.__head = node # 将新元素的节点赋给最前面的__head
        node.next.prev = node

    def append(self,item): # item不是节点 是具体的一个元素
    # '''链表尾部添加元素 尾插法'''
        node = Node(item)
        if self.is_empty(): # 空列表 直接到头上
            self.__head = node
        else:
            current = self.__head
            while current.next != None:
                current = current.next
            current.next = node
            node.prev = current
            
    def search(self,item):
    # '''查找节点是否存在'''
        current = self.__head
        while current != None:
            if current.elem == item:
                return True
            else:
                current = current.next
        return False

指定位置插入节点

指定位置插入节点

    def insert(self,pos,item):
    # '''指定位置添加元素 pos:从0开始的'''
        if pos <= 0:
            self.add(item)
        elif pos > (self.length() - 1):
            self.append(item)
        else:
            current = self.__head
            count = 0
            while count < pos:
                count += 1
                current = current.next
            # 循环退出后 pre指向了pos减一的位置
            node = Node(item)
            node.next = current # 插入到链表元素之间
            node.prev = current.prev
            current.prev.next = node
            current.prev = node

删除元素

删除元素

    def remove(self,item):
    # '''删除节点'''
        current = self.__head
        pre = None
        while current != None:
            if current.elem == item:
                # 先判断此节点是否是头结点
                # 如果是头结点的话
                if current == self.__head:
                    self.__head = current.next
                    if current.next != None:
                        # 判断链表是否只有一个节点
                        current.next.prev = None
                    break
                else:
                    current.prev.next = current.next # 这两部是核心步骤
                    if current.next:
                        current.next.prev = current.prev
                    break
            else:
                current = current.next

测试:

if __name__ == "__main__":
    ll = DoubleLinkList()
    print(ll.is_empty())
    print(ll.length())
    print('---')
    print(ll.is_empty())
    print(ll.length())
    print('---')
    ll.append(1)
    ll.append(2)
    ll.append(3)
    ll.append(4)
    ll.append(5)
    ll.append(6)
    ll.add(100) # 添加到头部
    ll.travel()
    print('\n---')
    ll.insert(2,99)
    ll.travel()
    print('\n---')
    ll.insert(-1,12)
    ll.travel()
    print('\n---')
    ll.insert(99,89)
    ll.travel()
    print('\n---')
    ll.remove(12)
    ll.travel()
    print('\n---')
    ll.remove(6)
    ll.travel()
    print('\n---')
    ll.travel()
    print(ll.search(3))

输出结果:

True
0
---
True
0
---
100 1 2 3 4 5 6 
---
100 1 99 2 3 4 5 6 
---
12 100 1 99 2 3 4 5 6 
---
12 100 1 99 2 3 4 5 6 89 
---
100 1 99 2 3 4 5 6 89 
---
100 1 99 2 3 4 5 89 
---
100 1 99 2 3 4 5 89 True

单项循环链表

单链表的一个变形是单向循环链表,链表中最后一个节点的next域不再为None,而是指向链表的头节点。
单项循环链表

class Node(object):
    '''节点'''
    def __init__(self,elem):
        self.elem = elem # elem是存放数据的元素
        self.next = None # next是下一个节点的标识

# node = Node(100)
class SingleCycleLinkList(object):
    '''单项循环链表的操作'''
    def __init__(self,node = None):
    # '''这个目的是把头结点连上 是为了方便调用下面的方法'''
        self.__head  = node
        if node:
            node.next = node # 使其收尾相连

    def is_empty(self):
    # '''链表是否为空'''
        return self.__head == None

    def length(self):
    # '''链表长度'''
        if self.is_empty():
            return 0
    # current游标,用来移动遍历节点
        current = self.__head
        # count 记录数量
        count = 1
        while current.next != self.__head:
            count += 1
            current = current.next
        return count # 移动了几位就是链表长度是多少

    def travel(self):
    # '''遍历整个链表'''
        if self.is_empty():
            return '空列表'
        current = self.__head
        while current.next != self.__head:
            print(current.elem,end=' ')
            current = current.next
        # 退出循环时 current指向尾结点 但尾结点的元素未打印 现在要打印
        print(current.elem)

    def add(self,item):
    # '''链表头部添加元素 头插法'''
        node = Node(item)
        if self.is_empty():
            self.__head == node
            node.next = node
        else:
            current = self.__head
            while current.next != self.__head:
                current = current.next # 只要不到列表的头就要一直往后移动
            # 退出循环 current指向尾结点
            node.next = self.__head
            self.__head = node
            # current.next = node
            current.next = self.__head

    def append(self,item): # item不是节点 是具体的一个元素
    # '''链表尾部添加元素 尾插法'''
        node = Node(item)
        if self.is_empty(): # 空列表 直接到头上
            self.__head = node
            node.next = node # 只要不到列表的头就要一直往后移动
        else:
            current = self.__head
            while current.next != self.__head:
                current = current.next
            # current.next = node
            node.next = self.__head
            current.next = node

    def insert(self,pos,item):
    # '''指定位置添加元素 pos:从0开始的'''
        if pos <= 0:
            self.add(item)
        elif pos > (self.length() - 1):
            self.append(item)
        else:
            pre = self.__head
            count = 0
            while count <= (pos-1):
                count += 1
                pre = pre.next
            # 循环退出后 pre指向了pos减一的位置
            node = Node(item)
            node.next = pre.next
            pre.next = node

    def remove(self,item):
    # '''删除节点'''
        if self.is_empty():
            return '空字符串'
        current = self.__head
        pre = None
        while current.next != self.__head:
            if current.elem == item:
                # 先判断此节点是否是头结点
                # 如果是头结点的话
                if current == self.__head:
                    # 头结点处理
                    # 找尾结点 rear 尾部的意思
                    rear = self.__head
                    while rear.next != self.__head:
                        rear = rear.next
                    self.__head = current.next
                    rear.next = self.__head
                    # self.__head = current.next
                else:
                    # 中间节点处理
                    pre.next = current.next # 核心步骤 删除步骤
                return
            else:
                pre = current
                current = current.next
        # 退出循环 current指向尾结点
        if current.elem == item:
            if current == self.__head:
                # 链表只有一个节点
                self.__head = None
            else:
                pre.next = current.next  # 核心步骤 删除步骤

    def search(self,item):
    # '''查找节点是否存在'''
        if self.is_empty():
            return False
        current = self.__head
        while current != self.__head:
            if current.elem == item:
                return True
            else:
                current = current.next
        # 退出循环 current指向了尾结点
        if current.elem == item:
            return True
        return False

# 测试
if __name__ == "__main__":
    ll = SingleCycleLinkList()
    print(ll.is_empty())
    print(ll.length())
    print('---')
    print(ll.is_empty())
    print(ll.length())
    print('---')
    ll.append(1)
    ll.append(2)
    ll.append(3)
    ll.append(4)
    ll.append(5)
    ll.append(6)
    ll.add(100) # 添加到头部
    ll.travel()
    print('\n---')
    ll.insert(2,99)
    ll.travel()
    print('\n---')
    ll.insert(-1,12)
    ll.travel()
    print('\n---')
    ll.insert(99,89)
    ll.travel()
    print('\n---')
    ll.remove(12)
    ll.travel()
    print('\n---')
    ll.remove(6)
    ll.travel()
    print('\n---')
    ll.travel()
    print(ll.search(3))

输出结果:

True
0
---
True
0
---
100 1 2 3 4 5 6

---
100 1 2 99 3 4 5 6

---
12 100 1 2 99 3 4 5 6

---
12 100 1 2 99 3 4 5 6 89

---
100 1 2 99 3 4 5 6 89

---
100 1 2 99 3 4 5 89

---
100 1 2 99 3 4 5 89
False
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值