python抽象数据类型——单链表全功能解释

1.首先我们要清楚python中不同的一点,python中的变量不是数据存储地址的别名,而是一个指向数据存储地址的指针,所以为什么python中没有指针,就是因为变量本身就是指针。例如python中的交换变量。 

a = 1
b = 99
print(a,b)
a,b = b,a
print(a, b)

 返回值:

F:\测试>python -u "f:\测试\测试文档.py"
1 99
99 1
原理图解

2.然后就是链表,链表由节点组成,节点由一个数据区和一个指针组成,就像一串手链一样,节点之间依次用指针连接起来,所以我们为了创建链表,要先创建一个能够生成节点的类。

class Node:
    '''定义节点类,用来获取新节点'''       
    def __init__(self,elem):
        self.elem = elem
        self.next = None

我们观察这个类,里面由我们上面提到的两个元素,即数据区(self.elem)指针(self.next)。有了节点类后我们就可以创建链表类了。

class singlelinklist:
    def __init__(self):
        self.__head = None    #定义一个头指针,用来取第一个节点

在初始化里,我们引入一个头指针self.__head,并且定义成私有变量 ,这样可以才取到第一个节点。有了这两个类,我们就有了链表的外框。然后我们就需要在链表类内部定义方法,包括判定为空,查看链表长度,遍历链表以及增 删 改 查


3.首先是判定是否为空,判定是否为空,我们不需要额外输入参数,直接返回bool值即可。

    def is_empty(self):
        '''判断是否为空'''
        return self.__head == None   #直接返回头指针的内容即可

return后面的式子即判断头指针指向的内容,如果为空,说明一个节点都没有,即为空。


4.查看链表长度

    def length(self):
        '''输出链表的节点数,即链表长度'''
        cur = self.__head   #定义一个自由指针
        count = 0           #计数
        while cur != None:  #该终止条件,让cur可以停在链表尾指向的 None
            cur = cur.next  #往后移动一次自由指针
            count += 1   
        return count        #遍历结束后,返回计数值

查看链表长度,我们则需要遍历链表,所以要引入一个自由指针(cur),cur要先指向第一个节点,即通过头指针指向第一个节点。然后再用count来计数,cur前进一步(即把cur.next赋给cur)计数加一,最后遍历结束指向None时,count即为链表总节点数,返回计数值即可。注意,while的停止条件为关键,可以控制cur最后指向的位置。

原理图 


 5.遍历链表

    def travel(self):
        '''遍历并打印链表'''
        cur = self.__head
        while cur != None:
            print(cur.elem,end=' ')
            cur = cur.next

遍历链表和上面测量链表长度的循环原理一样,循环时把每个节点的数据区打印出来。


6.头插法

    def add(self,elem):
        '''头插法'''
        node = Node(elem)   #获取一个新节点,存入我们输入的元素
        node.next = self.__head   #让新节点的指针指向第一个节点
        self.__head = node        #让头节点指向新节点

头插法,就是在头指针(__head)头结点(node)之间插入一个新节点,所以我们先用node实例化Node类,让其成为一个节点对象,然后先让新节点指向之前的头结点不打乱原链表的结构,再让头指针指向新节点。

原理图:


7.尾插法 

    def append(self,elem):
        '''尾插法'''
        node = Node(elem)   
        cur = self.__head
        if self.is_empty():   #如果链表为空
            self.__head = node  #则让头指针指向新节点
        else:
            while cur.next != None:  #该终止条件,可以让cur停在最后一个节点上
                cur = cur.next       
            cur.next = node          #让尾节点指针指向新节点

尾插法头插法不同的点在于我们需要遍历一次链表,才可以找到尾节点,所以我们需要用到一个自由指针来在链表内循环,那么循环终止的条件是什么?就是要让自由指针最后指向尾节点。我们想出基本思路后,就要考虑极限问题如果链表为空,那么就要用头指针来指向新节点,所以我们还需要用到条件语句。 

原理图:


8.按索引插入节点 

   def insert(self,index,elem):
        '''在索引前面插入节点'''
        node = Node(elem)
        count = 0
        cur = self.__head
        if index < 0:       #如果输入的索引小于零,则为头插法
            self.add(elem)
        elif index > (self.length() - 1):  #输入的索引大于链表最大索引,则为尾插法
            self.append(elem)
        else:
            while count < index-1:     #让cur停在索引节点的前一个节点上
                count += 1
                cur = cur.next
            node.next = cur.next   #遍历结束后,先让新节点指针指向我们输入的索引节点,再让cur指针指向新节点
            cur.next = node

1.基本思路:我们需要找到索引位置,所以用到自由指针来遍历链表,且需要一个计数君,来帮助我们判断自由指针移动了几次,移动结束后,应该让自由指针指向索引位置的前一个节点,所以while的终止条件很重要!然后我们需要考虑极限情况如果我们输入的index小于零,那我们就按照头插法处理,如果index大于链表最大,就按照尾插法处理

2.原理图:注意应该先完成node的指针操作,不破坏原链表的结构的情况下,悄悄的改变链表中的指针。


9.删除元素

    def remove(self,elem):
        '''删除输入的元素'''
        pre = None          #再引入一个指针,用来指向cur的前一个节点,我们称之为 前指针
        cur = self.__head
        while cur != None: 
            if cur.elem == elem:  #判断cur指向节点的元素是否等于我们输入的元素
                if cur == self.__head:   #再判断cur是否为头节点
                    self.__head = cur.next   #让头指针指向cur的下一个节点
                else:
                    pre.next = cur.next   #不是头节点,则让前指针指向节点的指针指向cur指向节点指向的下一个节点
                break
            else:
                pre = cur     #如果不是我们输入的元素,则让前指针移动至cur位置,再让cur后移一位
                cur = cur.next

1.删除节点,即让被删除节点的前一个节点的指针指向被删除节点的下一个节点从而被删除节点就不存在于链表中了,那么我们需要两个指针,一个(cur)用来指向被删除节点,一个(pre)用来指向前一个节点,遍历链表时,让两个指针一前一后的移动,pre始终应该指向cur指向节点的前一个节点。当我们遍历到需要删除的节点时,我们要先判断节点内数据区是否为我们输入的elem,如果是,就用pre和cur两个指针来删除该节点。

2.考虑极限情况:如果删除的是头结点,我们则需要改变头指针(head)的指向,就不是改变pre指针的指向了。 尾节点的话,我们依然可以用pre和cur指针来完成删除操作。

3.原理图:


10.搜查元素是否存在

    def search(self,elem):
        '''搜查该元素是否存在链表中'''
        cur = self.__head
        while cur != None:
            if cur.elem == elem:    #遍历链表时,若遍历到我们输入的元素,则返回bool值:True
                return True
            else:                   
                cur = cur.next
        return False      #遍历结束没有找到就返回bool值:False

定义一个自由指针cur,然后遍历列表,并且用条件语句来判断节点内的数据区是否为我们输入的元素,遍历到了就返回True,遍历结束后如果都没有返回值就说明链表中没有我们输入的元素,就返回False


10.总代码

class Node:
    '''定义节点类,用来获取新节点'''       
    def __init__(self,elem):
        self.elem = elem
        self.next = None

class singlelinklist:
    def __init__(self):
        self.__head = None    #定义一个头指针,用来取第一个节点
    def is_empty(self):
        '''判断是否为空'''
        return self.__head == None   #直接返回头指针的内容即可

    def length(self):
        '''输出链表的节点数,即链表长度'''
        cur = self.__head   #定义一个自由指针
        count = 0           #计数
        while cur != None:  #该终止条件,让cur可以停在链表尾指向的 None
            cur = cur.next  #往后移动一次自由指针
            count += 1   
        return count        #遍历结束后,返回计数值
    
    def travel(self):
        '''遍历并打印链表'''
        cur = self.__head
        while cur != None:
            print(cur.elem,end=' ')
            cur = cur.next

    def add(self,elem):
        '''头插法'''
        node = Node(elem)   #获取一个新节点,存入我们输入的元素
        node.next = self.__head   #让新节点的指针指向第一个节点
        self.__head = node        #让头节点指向新节点
    
    def append(self,elem):
        '''尾插法'''
        node = Node(elem)   
        cur = self.__head
        if self.is_empty():   #如果链表为空
            self.__head = node  #则让头指针指向新节点
        else:
            while cur.next != None:  #该终止条件,可以让cur停在最后一个节点上
                cur = cur.next       
            cur.next = node          #让尾节点指针指向新节点

    def insert(self,index,elem):
        '''在索引前面插入节点'''
        node = Node(elem)
        count = 0
        cur = self.__head
        if index < 0:       #如果输入的索引小于零,则为头插法
            self.add(elem)
        elif index > (self.length() - 1):  #输入的索引大于链表最大索引,则为尾插法
            self.append(elem)
        else:
            while count < index-1:     #让cur停在索引节点的前一个节点上
                count += 1
                cur = cur.next
            node.next = cur.next   #遍历结束后,先让新节点指针指向我们输入的索引节点,再让cur指针指向新节点
            cur.next = node
    
    def remove(self,elem):
        '''删除输入的元素'''
        pre = None          #再引入一个指针,用来指向cur的前一个节点,我们称之为 前指针
        cur = self.__head
        while cur != None: 
            if cur.elem == elem:  #判断cur指向节点的元素是否等于我们输入的元素
                if cur == self.__head:   #再判断cur是否为头节点
                    self.__head = cur.next   #让头指针指向cur的下一个节点
                else:
                    pre.next = cur.next   #不是头节点,则让前指针指向节点的指针指向cur指向节点指向的下一个节点
                break
            else:
                pre = cur     #如果不是我们输入的元素,则让前指针移动至cur位置,再让cur后移一位
                cur = cur.next
    
    def search(self,elem):
        '''搜查该元素是否存在链表中'''
        cur = self.__head
        while cur != None:
            if cur.elem == elem:    #遍历链表时,若遍历到我们输入的元素,则返回bool值:True
                return True
            else:                   
                cur = cur.next
        return False      #遍历结束没有找到就返回bool值:False

测试代码:

l1 = singlelinklist()  #用l1实例化链表类
print(l1.is_empty())   #打印是否为空
print(l1.length())     #打印列表长度

l1.append(1)    #尾插法插入一个1
print(l1.is_empty())
print(l1.length())

l1.append(3)   #尾插一个3
l1.add(100)    #头插法插入一个100
print(l1.travel())

l1.insert(1,4)  #在索引为1的节点前面加入一个元素4
print(l1.travel()) #遍历链表

print(l1.search(3),l1.search(99)) #搜查3和99是否存在于链表中

l1.remove(100)  #除去元素100
print(l1.travel()) #遍历链表

返回值:

F:\测试>python -u "f:\测试\链表.py"
True
0
False
1
100 1 3 None
100 4 1 3 None
True False
4 1 3 None

说明功能都能正常运行(以上为自己的一些总结,欢迎大家一起讨论)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值