数据结构与算法Day3

链表概念以及单向链表操作

1.链表

顺序表储存时会申请连续的储存空间,若要修改数据时,需要进行整体的数据搬迁,较为麻烦。而链表能够灵活运用计算机的内存空间,较为灵活。

链表的定义

链表是一种常见的数据结构,是一种线性表,储存时一个节点有两个域,一个域为信息域,另一个域为链接域,信息域储存数据信息,链接域储存下一个数据信息的地址。

2.单向链表

单向链表又称为单链表,是链表中最简单的一种形式,包含一个头节点,n个节点,且最后一个节点的链接域指向空值。

 3.单向链表封装操作

class Node(object):
    def __init__(self,elem):
        self.elem = elem
        self.next = None
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.elem,end=' ')
            cur = cur.next
    def add(self,item):
        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):
        '''
        :param pos: 从0开始
        :param item:
        :return:
        '''
        if pos < 0:
            self.add(item)
        elif pos > (self.length()-1):
            self.append(item)
        else:
            pre = self.__head
            count = 0
            while count < (pos-1):
                pre = pre.next
                count += 1
            #循环退出后 pre指向pos-1的位置
            else:
                node = Node(item)
                node.next = pre.next
                pre.next = node
    def remove(self,item):
        #pre和cur 两个游标差一个位置
        pre = None
        cur = self.__head
        while cur != None:
            if cur.elem == item:
                #先判断当前节点是否为头节点
                #如果是头节点
                if cur == self.__head:
                    self.__head = cur.next
                else:
                    pre.next = cur.next
                break
            else:
                pre = cur
                cur = cur.next
    def search(self,item):
        cur = self.__head
        while cur != None:
            if cur.elem == item:
                return True
            else:
                cur = cur.next
        return False

=========================================================================

详解

节点的导入 

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

头节点定义 一般指向空 

class SingleLinkList(object):
    def __init__(self,node = None):
        self.__head = node

判断是否为空的函数定义

def is_empty(self):
    return(self.__head == None)#直接判断头节点是否指向空即可

判断链表长度的函数定义

def length(self):
    # cur 游标 用来移动遍历节点 从0开始
    cur = self.__head
    # count 计数
    count = 0
    while cur != None: #这个地方不是cur.next = None 不然会少计一个数
        count += 1
        cur = cur.next
    return count

遍历链表的函数定义

def travel(self):
    cur = self.__head #游标指向头节点
    while cur != None:#当游标不为空时 一直向下遍历并打印
        print(cur.elem,end=' ')
        cur = cur.next

头部添加元素的函数定义

def add(self,item):
    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 #当下一个链接域不指向为空 游标从0开始往下走
        while cur.next != None:
            cur = cur.next
        cur.next = node #当游标走到最后一个元素时 元素的链接域指向新的节点

 指定位置添加元素的函数定义

def insert(self,pos,item):
    '''
    :param pos: 从0开始走 查找位置
    '''
    if pos < 0: #如果输入的位置小于零 判断为在头节点之前 插入元素 即为头部位置添加元素
        self.add(item)
    elif pos > (self.length()-1):#如果输入位置为最后一个元素的位置 判断为在尾部位置添加元素
        self.append(item)
    else: #找到指定位置的前一个位置 让pre的链接域指向新的节点
        pre = self.__head
        count = 0
        while count < (pos-1):#找到指定位置的前一个节点
            pre = pre.next
            count += 1
        #循环退出后 pre指向pos-1的位置
        node = Node(item) #导入新的节点
        node.next = pre.next #新节点的链接域指向前一个节点的链接域
        pre.next = node

删除节点的函数定义

不是删除某个节点的操作 只是改变一个节点的链接域指向

def remove(self,item):
    #pre和cur 两个游标差一个位置 也可以只写pre游标 最后令pre.next = pre.next.next
    pre = None
    cur = self.__head
    while cur != None:
        if cur.elem == item:
            #先判断当前节点是否为头节点
            #如果是头节点
            if cur == self.__head:
                self.__head = cur.next
            else:
                pre.next = cur.next
            break
        else:# 遍历
            pre = cur
            cur = cur.next

 查找节点是否存在的函数定义

def search(self,item):
    cur = self.__head
    while cur != None:
        if cur.elem == item:
            return True
        else:
            cur = cur.next
    return False

4.链表和顺序表操作时间复杂度的对比

操作链表顺序表
访问元素O(n)O(1)
在头部插入/删除O(1)O(n)
在尾部插入/删除O(n)O(1)
在中间插入/删除O(n)O(n)

访问元素 顺序表只需要访问对应的物理地址 而链表需要一个一个遍历

在头部数据操作上 链表只需要改变两个节点的链接域 而顺序表需要进行数据的搬迁

在尾部数据操作上 顺序表只需要找到对应的物质地址并添加元素 而链表需要遍历到最后一个cur.next = None时 再添加进新节点的链接域

在中间数据操作上 时间复杂度均为O(n) 但链表的O(n)是节点遍历造成的 而顺序表的O(n)是由于数据搬迁造成的

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值