python数据结构之线性表

线性表的基本概念

线性表(Linear List)是其组成元素间具有线性关系的一种线性结构,是由
个具有相同数据类型(字符串、整数、浮点数、对象或其他更复杂的信息)的数据元素构成的有限序列,一般表示为:

{a1,a2,a3,a4,a5,…}

i 代表数据元素在线性表中的位序号( 0 <= i < n)
n 是线性表中的元素个数,称为线性表的长度

线性表的两种存储结构

顺序存储结构
优缺点

优点:
1.尾插效率高,便于随机访问
2.cpu缓存利用率高
3.存取速度高效,通过下标来直接存储

缺点:
1.不利于插入和删除操作
2.不可以增长长度

链式存储结构
  1. 单链表
  2. 双链表
  3. 循环列表
优缺点

优点:
1.物理存储单元上非连续,而且采用动态内存分配,能够 有效的分配和利用内存资源
2.节点删除和插入简单,不需要内存空间的重组。

缺点:
1.不能进行索引访问,只能从头结点开始顺序查找
2.数据结构较为复杂,需要大量的 指针操作,容易出错

顺序表

1.初始化顺序表

初始化顺序表时献给顺序表分配内存空间

def _init_(self,max):
    """
    初始化
    :param max:顺序表的最大容量
    """
    self.max = max
    self.index = 0
    self.data - [None for _ in range(self.max)]

在Python中通常实例对象初始化时会用到__init__方法
例如,下面的代码就创建了一个名叫 my_list 的实例

class MyList:
    def __init__(self, max):
        self.max = max
        self.index = 0
        self.data = [None for _ in range(self.max)]

my_list = MyList(10)
2.按下标值查找元素

如何下标值合法,则返回该下标值上的元素,否则抛出异常

    def __getitem__(self, index):
        if index < 0 or index >= self.index:
            raise IndexError('index非法')
        else:
            return self.data[index]

未来在这里以超链接的形式补充 异常处理 的内容

3.修改下标值为index的位置的元素

与第2点类似,一定要index合法才能修改,否则就抛出异常

    def __setitem__(self, index, value):
        if index < 0 or index >= self.index:
            raise IndexError('index非法')
        else:
            self.data[index] = value

注意!!!
在getitem和setitem方法中,index == self.index都会抛出异常
因为表的下标是从0 到 n-1,没有n下标

4.判断顺序表是否为空

若顺序表为空,self.index 为 0 ,所以只需要判断其是否为0就好了

    def empty(self):
        if self.index == 0:
            return True
        else:
            return False

当然也有更加优化的写法

return self.index == 0

另外要谨慎使用 is 这种写法,虽然它与 == 所表达的意思是一样的,用来判断是否相等

例如,在 Python 中,整数和字符串等简单对象的值是不可变的,所以对于相同的值,它们通常会被存储在相同的内存地址中,因此 is 运算符在这种情况下可以正确地比较两个对象是否相同。但是,对于一些可变对象,例如列表、字典等,即使它们包含相同的元素或键值对,它们也可能被存储在不同的内存地址中,因此使用 is 运算符比较它们时可能会得到错误的结果。

因此,建议在比较对象时,尽可能使用 == 运算符,只有在需要比较对象是否指向同一内存地址时,才使用 is 运算符。

python return self.index is 0

5.插入表头元素

如果顺序表以及达到最大容量,则退出,否则就在尾部插入元素

    def append(self, value):
        if self.index == self.max:
            return
        else:
            self.data[self.index] = value
            self.index += 1
6.在顺序表中任意位置插入元素 O(n)
    def insert(self, index, value):
        if index < 0 or index > self.index:
            raise IndexError('index非法')
        if index == self.max:
            self.append(value)
            # 直接raise IndexError('index非法')更好
        else:
            #self.data += [value]
            # 调用方法也可以self.append(value)
            for i in range(self.index, index, -1):
                self.data[i] = self.data[i - 1]
            self.data[index] = value
            self.index += 1

以下为优化版本,在代码上省略了一个if语句,但是上述代码更容易理解
如果是在最后一个位置插入的话,就不需要交换位置了

def insert(self,index,value):
    if index < 0 or index > self.index:
        raise IndexError('index非法')
    else:
        #self.append(value)
        for i in range(self.index,index,-1):
            self.data[i] = self.data[i - 1]
        self.data[index] = value
        self.index += 1

self.append(value) 书上是由这段代码的,但是我建议不要加,通过遍历的方法打印出来,数组最后会多一个元素,并且去掉不影响 insert 方法

self.data += [value]

7.删除表尾元素

相当于这个表的长度直接减少了一个

    def pop(self):
        if self.empty():
            return
        self.index -= 1
8.删除任意位置的元素

用for循环将index后面的所有元素都向前移动一个位置

    def delete(self,index):
        if self.empty() or index >= self.index:
            raise IndexError('Index非法')
        for i in range(index,self.index):
            self.data[i] = self.data[i + 1]
        self.index -= 1
9.获取顺序表的长度

顺序表的长度记录在 self.index 中,直接返回即可

    def length(self):
        return self.index
10.遍历顺序表

一个一个打印出来即可

    def traversal(self):
        for i in range(self.index):
            print(self.data[i],end = " ")
        print()

单链表

1.节点定义代码

值域用来存放节点的值,指针域用来存放节点的直接后继指针

class Node(object):
    def __init__(self,val):
        self.val = val#数据域
        self.next = None#后继节点的指针
2.初始化

声明头尾指针均指向空

class SingleLinkedList(object):
    def __init__(self):
        self.head = None
        self.tail = None

头节点是链表的入口,尾节点是链表的出口

3.判断是否为空

若表头指针指向空,则单链表为空

    def empty(self):
        return self.head is None
4.获取单链表长度

只能通过遍历整个单链表,若当前节点不为空,则单链表的长度加 1

    def length(self):
        size = 0
        #声明cur指针,用来遍历单链表
        cur = self.head
        while cur != None:
            size += 1
            cur = cur.next
        return size
5.头插入法

        ~~~~~~~        因为是在头插入的,所以首先判断链表是否为空
若为空则需要将self.head和self.tail都指向新节点
否则只需要将新节点的next指向原来的头节点,再将self.head指向新节点即可

因为在链表头插入节点时,新节点将成为新的头节点,而尾节点不需要改变,因此self.tail指向原来的头节点即可。

    def prepend(self,val):
        newNode = Node(val)
        if self.head is None:
            self.head = newNode
            self.tail = self.head
        else:
            newNode.next = self.head
            self.head = newNode

在这里插入图片描述

6.在中间插入节点
    def insert(self,index,value):
        #定义一个cur用来遍历链表
        cur = self.head
        #一直遍历到下标为index - 1的节点
        for i in range(index - 1):
            cur = cur.next
        #temp现在指向index - 1的元素,即index个节点
        temp = cur.next
        newNode = Node(value)
        #将新节点的后继指针指向temp
        newNode.next = temp
        #将index个节点的直接后继指针指向新节点
        cur.next = newNode

在这里插入图片描述

7.尾插入法

同样要判断链表是否为空

    def append(self,val):
        newNode = Node(val)
        if self.empty():
            self.head = newNode
            self.tail = newNode
        else:
            #尾节点的后继指针指向新节点
            self.tail.next = newNode
            #尾指针指向新节点
            self.tail = newNode
8.删除头节点
    def del_first(self):
        if self.empty():
            raise IndexError('链表为空')
        if self.length() == 1:
            #将头尾指针指向空
            self.head = None
            self.tail = None
        else:#链表长度大于 1
        #将头指针指向第二个节点
            self.head - self.head.next
9.删除尾节点
    def del_lat(self):
        if self.empty():
            raise IndexError('链表为空')
        if self.length() == 1:
            self.head = None
            self.tail = None
        else:
            pre = self.heal
            cur = pre.next

            while cur.next is not None:
                pre = cur
                cur = cur.next
            cut = None
            pre.next = None
            self.tail = pre
10.删除任意位置的节点
    def delete(self,index):
        #删除下标值为index位置的节点,即删除第index+1个节点
        if self.empty():
            raise IndexError('链表为空')
        if index < 0 or index >= self.length():
            raise IndexError('Index非法')
        if index == 0:
            self.del_first()
        elif index == self.length() - 1:
            self.del_last()
        else:
            pre = self.head
            #通过for循环使pre指针指向第index个节点
            for i in range(index - 1):
                pre = pre.next
            #delNode为第index+1个节点
            delNode = pre.next
            #next为index+2个节点
            next = delNode.next
            #第index个节点的直接后继指向第index + 2个节点,即删除第index + 1个节点
            pre.next = next

总结

下次再写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值