2020-11-15数据结构与算法 (3) :单向链表,双向链表和单向循环链表的插入,遍历,删除和查询

1411-李同学

发表文章数:148

热门标签

,
首页 » 数据结构 » 正文

链表

线性表:链表和顺序表的统称,一个线性表是某类元素的一个集合,还记录这元素之间的一种顺序关系。最基本的数据结构之一。

为什么要使用链表

链表可以充分利用计算机内存空间,实现灵活的内存动态管理。

链表的定义

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

链表的节点

一个节点由两部分组成,数据区和链接区。第一部分保存数据信息,第二部分保存下一个节点的数据信息地址。

2020-11-15数据结构与算法 (3) :单向链表,双向链表和单向循环链表的插入,遍历,删除和查询

单向链表

定义:

单链表是链表中最简单的一种形式,它的节点包含两个域,一个信息域和一个链接域。这个链接指向链表中的下一个节点。而最后一个节点的链接域则指向一个空值。

  • 表元素域用来存放具体数据

  • 链接域用来存放下一个节点的位置

  • 变量p指向链表的头节点的位置,从p出发能找到表中的任意节点。

2020-11-15数据结构与算法 (3) :单向链表,双向链表和单向循环链表的插入,遍历,删除和查询

Python中变量标识的本质

python中的变量名不保存值,保存值的地址。

2020-11-15数据结构与算法 (3) :单向链表,双向链表和单向循环链表的插入,遍历,删除和查询

变量等于谁即相当于该变量指向那个节点

单链表在python中的操作使用

链表与节点类的连接

2020-11-15数据结构与算法 (3) :单向链表,双向链表和单向循环链表的插入,遍历,删除和查询

统计一个链表的长度:游标指针

2020-11-15数据结构与算法 (3) :单向链表,双向链表和单向循环链表的插入,遍历,删除和查询
2020-11-15数据结构与算法 (3) :单向链表,双向链表和单向循环链表的插入,遍历,删除和查询

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

#node=Node()

class SingleLinkList(object):
    #单链表
    def __init__(self,node=None):
        #定义第一个指向的节点位置,头节点位置的属性为对象属性
        self.__head=node

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

    def length(self):
        #返回链表的长度
        # 遍历整个链表
        # cur游标用来移动遍历节点
        cur = self.__head
        # count记录数量
        count = 0
        while cur != None:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        cur=self.__head
        while cur != None:
            print(cur.item,end=" ")
            cur=cur.next
        print("/n")

    def add(self,item):
        #链表头部添加元素,头插法,先将新节点的next与原链表头部的数据地址连接,再将
        #head与新节点的数据element连接。
        node=Node(item)
        node.next=self.__head
        self.__head=node

    def append(self,item):
        #链表尾部添加元素,尾插法
        node=Node(item)
        if self.is_empty():
            self.__head=node
        else:
            cur=self.__head
            while cur.next != None:
                cur=cur.next
            cur.next=node

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


    def remove(self,item):
        #删除节点
        cur=self.__head
        pre=None
        while cur!=None: #如果是空链表,不执行操作
            if cur.item ==item:
                #先判断此节点是不是头节点。如果是头节点
                if cur==self.__head:
                    self.__head=cur.next
                else:
                    pre.next=cur.next
                break
            else:
                pre=cur
                cur=cur.next #需要先移动pre


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


#测试
if __name__=="__main__":
    ll=SingleLinkList()
    print(ll.is_empty())
    print(ll.length())
    ll.append(1)
    print(ll.is_empty())
    print(ll.length())
    ll.append(2)
    ll.append(3)
    ll.append(4)
    ll.travel()
    ll.add(100)
    ll.travel()
    ll.insert(6,20)
    ll.travel()
    ll.remove(3)
    ll.remove(1)
    ll.remove(20)
    ll.travel()

#后继节点

链表与顺序表的对比

2020-11-15数据结构与算法 (3) :单向链表,双向链表和单向循环链表的插入,遍历,删除和查询

链表与顺序表的对比

链表可以将分散的存储数据连接。适合存储数据量较大的存储。

链表的主要耗时操作是便利查找。顺序表查找很快,主要耗时操作时拷贝覆盖。因为除了目标元素在尾部的特殊情况。顺序表进行插入和删除时需要对操作点之后的所有元素进行后移位操作,只能通过拷贝和覆盖的方法进行。

双向链表:

2020-11-15数据结构与算法 (3) :单向链表,双向链表和单向循环链表的插入,遍历,删除和查询

双向链表:

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

  • 后继节点:当前节点的下一个

  • 前驱节点:当前节点的前一个

在头部插入元素

2020-11-15数据结构与算法 (3) :单向链表,双向链表和单向循环链表的插入,遍历,删除和查询

在尾部插入

2020-11-15数据结构与算法 (3) :单向链表,双向链表和单向循环链表的插入,遍历,删除和查询

Insert插入

2020-11-15数据结构与算法 (3) :单向链表,双向链表和单向循环链表的插入,遍历,删除和查询

remove

2020-11-15数据结构与算法 (3) :单向链表,双向链表和单向循环链表的插入,遍历,删除和查询

代码

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

class DoubleLinkList(object):

    def __init__(self,node=None):
        #定义第一个指向的节点位置,头节点位置的属性为对象属性
        self.__head=node

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

    def length(self):
        #返回链表的长度
        # 遍历整个链表
        # cur游标用来移动遍历节点
        cur = self.__head
        # count记录数量
        count = 0
        while cur != None:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        cur=self.__head
        while cur != None:
            print(cur.item,end=" ")
            cur=cur.next
        print("/n")

    def add(self,item):
        #链表头部添加元素,头插法,先将新节点的next与原链表头部的数据地址连接,再将
        #head与新节点的数据element连接。
        node=Node(item)
        node.next=self.__head
        self.__head.prev=node
        self.__head=node

    def append(self,item):
        #链表尾部添加元素,尾插法
        node=Node(item)
        if self.is_empty():
            self.__head=node
        else:
            cur=self.__head
            while cur.next != None:
                cur=cur.next
            cur.next=node
            node.prev=cur

    def insert(self,pos,item):
        #指定位置添加元素
        if pos<=0:
            self.add(item)
        elif pos > self.length()-1:
            self.append(item)
        else:
            count=0
            cur=self.__head

            node=Node(item)
            count=0
            while count < pos-1:
                cur=cur.next
                count+=1
            #当循环退出后cur指向pos的位置。
            node.next=cur
            node.prev=cur.prev
            cur.prev.next=node
            cur.prev=node


    def remove(self,item):
        #删除节点
        cur=self.__head
        while cur!=None: #如果是空链表,不执行操作
            if cur.item ==item:
                #先判断此节点是不是头节点。如果是头节点
                if cur==self.__head:
                    self.__head=cur.next
                    if cur.next: #判断链表是否只有一个节点
                        cur.next.prev=None
                else:
                    cur.prev.next=cur.next
                    if cur.next:
                        cur.next.prev=cur.prev
                break
            else:
                cur=cur.next #需要先移动pre


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

if __name__=="__main__":
    ll=DoubleLinkList()
    ll.append(9)
    ll.append(8)
    ll.append(7)
    ll.append(6)
    ll.append(5)
    ll.travel()
    ll.insert(2,15)
    ll.travel()
    ll.remove(9)
    ll.remove(5)
    ll.remove(8)
    ll.travel()

单向循环链表

让尾节点指向头节点。

单向循环链表的遍历和求长度

2020-11-15数据结构与算法 (3) :单向链表,双向链表和单向循环链表的插入,遍历,删除和查询

单向循环链表添加元素

头插法

2020-11-15数据结构与算法 (3) :单向链表,双向链表和单向循环链表的插入,遍历,删除和查询

尾插法

2020-11-15数据结构与算法 (3) :单向链表,双向链表和单向循环链表的插入,遍历,删除和查询

remove

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

#node=Node()

class SingleLinkList(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):
        #返回链表的长度
        # 遍历整个链表
        # cur游标用来移动遍历节点
        if self.is_empty():
            return 0
        cur = self.__head
        # count记录数量
        count = 1
        while cur.next != self.__head:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        cur=self.__head
        if self.is_empty():
            return
        while cur.next != self.__head:
            print(cur.item,end=" ")
            cur=cur.next
        # 退出循环时,cur指向尾节点,但尾节点的数据没有打印
        print(cur.item)


    def add(self,item):
        #链表头部添加元素,头插法,先将新节点的next与原链表头部的数据地址连接,再将
        #head与新节点的数据element连接。
        node=Node(item)
        if self.is_empty():
            self.__head=node
            node.next=node
        else:
            cur=self.__head
            while cur.next!=self.__head:
                cur=cur.next
            #退出循环后代表cur指向尾节点
            node.next=self.__head
            self.__head=node
            #cur.next=node
            cur.next=self.__head

    def append(self,item):
        #链表尾部添加元素,尾插法
        node=Node(item)
        if self.is_empty():
            self.__head=node
            node.next=node
        else:
            cur=self.__head
            while cur.next != self.__head:
                cur=cur.next
            cur.next=node
            node.next=self.__head

    def insert(self,pos,item): #不涉及到尾节点,所以不需要改变。
        #指定位置添加元素
        if pos<=0:
            self.add(item)
        elif pos > self.length()-1:
            self.append(item)
        else:
            pre=self.__head
            node=Node(item)
            count=0
            while count < (pos-1):
                pre=pre.next
                count+=1
            #当循环退出后pre指向pos-1的位置。
            node.next=pre.next
            pre.next=node


    def remove(self,item):
        #删除节点
        if self.is_empty():
            return
        cur=self.__head
        pre=None
        while cur.next !=self.__head: #如果是空链表,不执行操作
            if cur.item ==item:
                #先判断此节点是不是头节点。如果是头节点
                if cur==self.__head:
                    #头节点
                    #寻找到尾节点
                    rear=self.__head
                    while rear.next!=self.__head:
                        rear=rear.next
                    self.__head=cur.next
                    rear.next=self.__head
                else:
                    #中间节点
                    pre.next=cur.next
                return
            else:
                pre=cur
                cur=cur.next #需要先移动pre
        #退出循环,cur指向尾节点
        if cur.item==item:
            if cur==self.__head:
                #链表当中只有一个节点
                self.__head=None
            else:
                pre.next=cur.next


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

if __name__=="__main__":
    ll = SingleLinkList()
    ll.append(9)
    ll.append(8)
    ll.append(7)
    ll.append(6)
    ll.append(5)
    ll.travel()
    ll.insert(2, 15)
    ll.travel()
    ll.remove(9)
    ll.remove(5)
    ll.remove(8)
    ll.travel()
分享到:
赞(0) 打赏

评论 抢沙发

评论前必须登录!

  注册



长按图片转发给朋友

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

Vieu3.3主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录