数据结构及算法(Python)---单链表

来源:互联网 发布:机器小怪升级数据 编辑:程序博客网 时间:2024/06/11 20:09
"""   单链表   1、节点:      data: 数据      next: 下一个节点链接   2、操作:      is_empty() 链表是否为空      length() 链表长度      travel() 遍历整个链表      add(item) 链表头部添加元素      append(item) 链表尾部添加元素      insert(pos, item) 指定位置添加元素      remove(item) 删除节点      search(item) 查找节点是否存在      index(pos) 获取指定位置上元素"""class SingleNode(object):    """单链表节点"""    def __init__(self, data):        """        节点具有两部分内容,因此具有两个属性        :param data: 接收创建节点时的数据内容        """        self.data = data   # 存放数据        self.next = None   # 指向下一个节点,初始时为空class SingleLinkList(object):    """单链表"""    def __init__(self, node=None):        """        可以创建一个空链表,也可以创建带有一个节点的链表        :param node: 当创建带有节点的列表时,node用来接收节点数据,使用默认值用来创建空链表        """        self.__head = node    # 定义表头,方便操作使用,由于是类内部使用,所以定义为私有变量    def is_empty(self):        """        判断链表是否为空        :return: False 不为空, True 空        """        # 当链表中只有表头时则表示链表时空链表        if self.__head is None:            return True        else:            return False    def length(self):        """        链表长度:存在两种情况,空表和非空表        :return: 空表长度为0, 非空时,长度为节点个数(count)        """        count = 0            # 记录节点个数        # 1. 链表非空时,遍历所有节点        # 定义一个游标用于遍历整个链表,初始时指向表头指向的内容        cur = self.__head        # 由于初始时cur指向第一个节点,并且count=0,因此循环的终止条件是cur=None;当然也可以让count初始值为1,终止条件为cur.next=None        while cur is not None:            count += 1            cur = cur.next        return count        # 2. 链表为空时,长度为0;由于上面代码同样可以处理空链表的情况,因此空链表不需要特殊处理    def travel(self):        """        遍历整个链表        :return:        """        # 遍历和统计链表长度处理逻辑一样,唯一区别遍历是输入每个节点的data数据,而统计链表长度是记录节点数;        # 因此可以直接将length()中的代码复制,并将count += 1替换为print(cur.data, end="")即可        cur = self.__head        while cur is not None:            print(cur.data, end=" ")   # 同行输出            cur = cur.next        print("")                     # 遍历完后进行换行    def add(self, data):        """        链表头部添加元素:存在空表和非空表两种情况        :param data: 接收创建节点的数据        :return:        """        # 创建节点        newNode = SingleNode(data)        # 1. 非空表情况        newNode.next = self.__head   # 将新节点的next指向表头指向的节点        self.__head = newNode        # 将表头指向新节点        # 2. 空表情况,由于上面代码同样可以处理空链表的情况,因此空链表不需要特殊处理    def append(self, data):        """        链表尾部添加元素:同样存在空表、单个节点链表和多个节点链表情况        :param data: 接收创建节点的数据        :return:        """        # 创建节点        newNode = SingleNode(data)        # 1. 空表情况,等同于链表头部添加        if self.is_empty():            self.__head = newNode  # 将表头指向新节点            return        # 2. 非空表情况,则需要先找到最后一个节点(参照遍历链表的代码)        cur = self.__head        while cur.next is not None:            cur = cur.next        cur.next = newNode       # 将最后一个节点的next指向新节点        # 3. 单个节点链表,由于第2点的代码同样可以处理单节点链表的情况,因此单节点链表不需要特殊处理    def insert(self, pos, data):        """        指定位置添加元素:        --插入的位置pos存在三种情况 1)链表头部位置pos=0 2)链表尾部位置pos=length() 3)链表中间位置pos=[1,length()-1]        --链表存在空表、非空表(就上面3中情况)        --用户输入pos也存在<0或>length()情况        :param pos: 新节点插入的位置,于列表一样,此处同样以0下标开始        :param data:  新节点数据        :return:        """        # 1、首先处理异常情况(即:用户输入pos也存在<0或>length()的情况)        if pos < 0 or pos > self.length():            print("索引位置越界!")        # 2. 链表头部位置pos=0,同样适应于空表情况        elif pos == 0:            self.add(data)                # 直接调用链表头部插入函数        # 3. 链表尾部位置pos=length()        elif pos == self.length():            self.append(data)             # 直接调用链表尾部插入函数        # 4. 链表中间位置插入pos=[1,length()-1]        else:            # 创建节点            newNode = SingleNode(data)            # 定义游标            cur = self.__head            # 记录下标位置            index = 0            # 当游标移动要插入位置pos的前一个位置时,停止移动            while index < pos-1:                index += 1                cur = cur.next            newNode.next = cur.next    # 将新节点的next执行pos位置上的节点            cur.next = newNode         # 将pos前一个位置上的节点的next指向新节点    def remove(self, data):        """        删除节点: 存在情况 1)空表  2)未找到指定节点 3)单节点链表 4)删除节点在链表头部 5)删除节点在链表中间  6)删除节点在链表尾部        :param data: 要删除的数据        :return: 删除成功True, 未找到数据False        """        # 首先处理删除节点在链表中间的情况,需要使用两个游标进行处理,        cur = self.__head  # 定义游标(指向当前位置)        pre = None         # 定义游标(指向上一个节点位置)        while cur is not None:             # 同样适应空列表 1            if cur.data == data:                if cur == self.__head:         # 头节点(同样适应单节点链表) 3,4                    self.__head = cur.next     # 变成空链表                else:                    pre.next = cur.next    # 将上一个节点的next指向当前节点的next(也就是当前节点的下一个节点位置) 5,6                break            else:                pre = cur              # 向后移动                cur = cur.next        return False                   # 未找到数据  2    def search(self, data):        """        查找节点是否存在:存在空表的特殊情况        :param data: 要查找的数据        :return: 返回查找到的位置索引,未查找到则返回-1        """        index = 0                  # 索引下标        cur = self.__head          # 定义游标        while cur is not None:     # 循环到cur指向最后一个节点的next,也就是None是结束(同样适用于空表)            if cur.data == data:   # 查到到数据                return index       # 返回位置的索引下标            index += 1            cur = cur.next        return -1                  # 未找到数据    def index(self, pos):        """        获取指定位置上的数据:存在空表的特殊情况        :param pos: 要查找的位置, 索引位置从0开始        :return: 返回查找到的数据        """        index = 0                  # 索引下标        cur = self.__head          # 定义游标        while cur is not None:     # 循环到cur指向最后一个节点的next,也就是None是结束(同样适用于空表)            if index != pos:                cur = cur.next                index += 1            else:                return cur.data     # 返回指定位置上的数据        return None                 # 传入的索引位置超出[0~length()-1]范围或链表为空时返回Noneif __name__ == '__main__':    sll = SingleLinkList()    print("空否:", sll.is_empty())    print("长度:", sll.length())    sll.add(1)    sll.append(3)    sll.insert(1, 2)    print("空否:", sll.is_empty())    print("长度:", sll.length())    # 1,2,3    sll.travel()    sll.insert(0, 'ooo')    sll.insert(-1, 'aaa')    sll.insert(4, 'bbbb')    sll.insert(7, 'cccc')    print("空否:", sll.is_empty())    print("长度:", sll.length())    # 'ooo',1,2,3,'bbbb'    sll.travel()    print(sll.search('bbbb'))   # 5    print(sll.search('aaaaa'))  # -1    sll.remove('ooo')    sll.travel()    sll.remove('bbbb')    sll.travel()    sll.remove('1')    sll.travel()    print("长度:", sll.length())    print('0', sll.index(0))    print('3', sll.index(3))    print('-1', sll.index(-1))    print('10', sll.index(10))    newNode = SingleNode('hhhhhhh')    sll2 = SingleLinkList(newNode)    print("空否:", sll2.is_empty())    print("长度:", sll2.length())    sll2.travel()

执行结果:

空否: True长度: 0空否: False长度: 31 2 3 索引位置越界!索引位置越界!空否: False长度: 5ooo 1 2 3 bbbb 4-11 2 3 bbbb 1 2 3 1 2 3 长度: 30 13 None-1 None10 None空否: False长度: 1hhhhhhh 
原创粉丝点击