【数据结构】链表

目录

 

4.1链表

4.1.1单链表

4.1.2单项循环链表

4.1.3双向链表


4.1链表

4.1.1单链表

# 结点
class SingleNode:
    def __init__(self,item):
        # 存放数据元素
        self.item=item
        # 存放下一个结点标识
        self.next=None
        
# 单项链表的实现
class SimgleLinkList:
    # 初始化链表
    def __init__(self):
        self._head=None
        
    # 向前插入值
    def add(self,item):
        node=SingleNode(item)
        node.next=self._head
        self._head=node
    
    # 指定链表位置插入元素的值
    def insert(self,index,item):
        if index<=0:
            self.add(item)
        elif index>=self.length():
            self.append(item)
        else:
            node=SingleNode(item)
            cur=self._head
            count=0
            while count<index-1:
                cur=cur.next
                count+=1
            node.next=cur.next
            cur.next=node
    
    # 向链表元素之后插入值
    def append(self,item):
        node=SingleNode(item)
        
        if self._head==None:
            self._head=node
            return None
             
        cur=self._head
        while True: # 如果当前结点的下一个结点为None
            if cur.next==None:
                cur.next=node
                break
            else:
                cur=cur.next
    
    # 删除最后一个元素,并返回删除的元素
    def pop(self):
        if self.isempty():
            return -1
        cur=self._head
        count=0
        pop_value=None
        while True:
            if count==self.length()-2:
                pop_value=cur.next.item
                cur.next=None
                break
            count+=1
            cur=cur.next
        return  pop_value 
    
    # 根据元素本身删除链表中的元素,如果元素不存在,我们返回-1
    def remove(self,elem):
        pow=self.search(elem)
        #  如果没有找到该元素,我们就返回-1
        if pow==-1:
            return -1
        cur=self._head  # 找到链表的头的位置
        count=0
        pre=None
        while True:
            if pow==self.length()-1:  # 说明删除的是最后一个元素
                self.pop()
                break
            elif pow==0:  # 如果删除的元素是第一个元素
                self._head=cur.next  # 将当前元素的下一个元素作为_head,删除了当前元素
                break
            else:  # 如果不是最后一个元素,那么被删除的元素就有下一个元素
                pre=cur  # 当前结点作为前一个结点
                cur=cur.next  # 当前结点后移一位
                count+=1
                if pow==count:  # 如果说指定位置等于要删除的位置
                    pre.next=cur.next  # 将当前结点指向当前结点的前一个位置
                    break
    
    # 元素的替换,指定位置替换成指定元素,如果替换的位置超出范围,返回-1
    def replace(self,index,elem):
        if index>=self.length():
            return -1
        cur=self._head
        count=0
        
        while True:
            if count==index:
                cur.item=elem  # 将我们的当前元素替换成该元素
                break
            cur=cur.next
            count+=1
        return 1
    # 查找指定元素的位置
    def search(self,elem):        
        cur=self._head
        count=0
        while True:
            if count>=self.length():
                return -1
            elif cur.item==elem:
                return count
            else:
                count+=1
                cur=cur.next
        return count       
    
    # 遍历链表
    def travel(self):
        cur=self._head
        while cur!=None:
            print(cur.item)
            cur=cur.next
    
    # 获取链表的长度
    def length(self):
        count=0
        cur=self._head
        while True:
            if cur!=None:
                count+=1
                cur=cur.next
            else:
                break
        return count
    
    # 判断链表是否为空
    def isempty(self):
        if self._head==None:
            return True
        return False

测试代码

single=SimgleLinkList()
single.append(1)
single.append(2)
single.append(3)
single.append(4)
single.remove(4)
print('--------',single.replace(4,10))
single.travel()

4.1.2单项循环链表

单项循环链表的最后一个节点的next不是指向None,而是指向头节点

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


# %%
class SingleCycLinkedList:
    def __init__(self):
        self._head = None

    # 判断节点是否为空
    def is_empty(self):
        return self._head == None

    # 头部添加元素
    def add(self, item):
        node = Node(item)
        if self.is_empty():  # 如果链表为空
            self._head = node
            node.next = self._head
        else:
            # 目标:node的next指向head,链表的最后节点的next指向node
            node.next = self._head
            cur = self._head
            while True:
                # 如果当前结点的下一个结点指向的是头结点,
                # 说明当前结点已经是该圈的最后一个节点了
                if cur.next == self._head:
                    break
                cur = cur.next
            cur.next = node
            self._head = node  # _head只是一个指向头结点的索引,头改变了,_head指向也应该发生改变

    # 尾部添加元素
    def append(self, item):
        node = Node(item)
        if self.is_empty():
            self._head = node
            node.next = self._head
        node.next = self._head
        cur = self._head
        while True:
            if cur.next == self._head:
                cur.next = node
                break
            cur = cur.next

            # 遍历

    def travel(self):
        if self.is_empty():
            return None
        cur = self._head
        while True:
            print(cur.item)  # 打印当前结点的值
            if cur.next == self._head:  # 如果当前结点没有next,那么直接退出循环
                break
            cur = cur.next  # 如果当前结点有下一个值,我们就将当前结点指向向下一个结点    

    def insert(self, index, item):

        if self.is_empty():
            self._head = node
            node.next = self._head
        elif index <= 0:
            self.add(item)
        elif index >= self.length():
            self.append(item)
        else:
            cur = self._head
            count = 0
            while True:
                if index >= count:
                    break
                count += 1

    def length(self):
        count = 0
        if self.is_empty():
            return count
        count += 1
        cur = self._head
        while True:
            if cur.next == self._head:
                break
            count += 1
            cur = cur.next
        return count


# %%
scll = SingleCycLinkedList()
for i in range(4):
    scll.append(i)

print('---------------')
scll.insert(4, 10)
scll.travel()

4.1.3双向链表

既有指向上一个节点的指针也有指向下一个节点的指针.

class Node(object):
    """双向链表节点"""
    def __init__(self, item):
        self.item = item
        self.next = None
        self.prev = None

class DLinkList(object):
    """双向链表"""
    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:
            count += 1
            cur = cur.next
        return count

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

    def add(self, item):
        """头部插入元素"""
        node = Node(item)
        if self.is_empty():
            # 如果是空链表,将_head指向node
            self._head = node
        else:
            # 将node的next指向_head的头节点
            node.next = self._head
            # 将_head的头节点的prev指向node
            self._head.prev = node
            # 将_head 指向node
            self._head = node

    def append(self, item):
        """尾部插入元素"""
        node = Node(item)
        if self.is_empty():
            # 如果是空链表,将_head指向node
            self._head = node
        else:
            # 移动到链表尾部
            cur = self._head
            while cur.next != None:
                cur = cur.next
            # 将尾节点cur的next指向node
            cur.next = node
            # 将node的prev指向cur
            node.prev = cur

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

    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的prev指向cur
            node.prev = cur
            # 将node的next指向cur的下一个节点
            node.next = cur.next
            # 将cur的下一个节点的prev指向node
            cur.next.prev = node
            # 将cur的next指向node
            cur.next = node

    def remove(self, item):
        """删除元素"""
        if self.is_empty():
            return
        else:
            cur = self._head
            if cur.item == item:
                # 如果首节点的元素即是要删除的元素
                if cur.next == None:
                    # 如果链表只有这一个节点
                    self._head = None
                else:
                    # 将第二个节点的prev设置为None
                    cur.next.prev = None
                    # 将_head指向第二个节点
                    self._head = cur.next
                return
            while cur != None:
                if cur.item == item:
                    # 将cur的前一个节点的next指向cur的后一个节点
                    cur.prev.next = cur.next
                    # 将cur的后一个节点的prev指向cur的前一个节点
                    cur.next.prev = cur.prev
                    break
                cur = cur.next

测试代码:

if __name__ == "__main__":
    ll = DLinkList()
    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(4)
    ll.remove(1)
    print "length:",ll.length()
    ll.travel()

面试题:如何判断带环链表?

我们声明两个指针,一个指针变化的速度快在前面跑,另一个指针变化的慢在后面缀,在运行的过程中,如果返现突然两个指针相遇了,那么说明该链表中一定存在环,否则不存在,如果不存在遍历完整个链表总会出来某个节点的next指针指向None.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值