单链表的节点包含元素域和链接域,链接域指向链表中的下一个节点,而尾节点则指向空


- 表元素域elem用来存放具体的数据
- 链表next用来存放下一个节点的位置
- 变量p指向链表的头结点的位置,从p出发找到表中的任意节点
单链表的操作
| 方法名 | 说明 |
|---|---|
| is_empty() | 链表是否为空 |
| length() | 链表长度 |
| travel() | 遍历整个链表 |
| add(item) | 链表头部添加元素 |
| append(item) | 链表尾部添加元素 |
| insert(pos,item) | 指定位置添加元素 |
| remove(item) | 删除节点 |
| search(item) | 查找节点是否存在 |
构造节点
# 封装节点类#构造节点class Node(object):def __init__(self,elem):#构造函数初始化self.elem=elem #创建一个数据self.next=None #链接区指向空
链表的构造
#构造链表class SingleLinkList(object):def __init__(self,node=None):self.__head=node#定义__head指针指向头节点node

- 创建初单链表类,初始化单链表的对象
- 传入node节点,并初始化,防止用户不传节点
- 创建一个__head指针,指向None
- __head=None:设头节点为私有属性,对外不需要知道其属性
- __head=node:传入头节点;当用户不传节点,则指向空
1.判断链表是否为空
if self.__head==None:return Trueelse:return False
#判断是否为空def is_empty(self):return(self.__head==None)
- 当__head指针指向空就是空链表
- 利用return可直接返回True或False
2.计算链表长度
- 定义一个cur游标(指针)用来遍历节点,并把__head指向的数据赋值给游标

- 定义一个计数器count用于计数
- 设置count的值为0(可以处理链表为空的情况)
- 设置循环语句,让count一直加+1
- 设置循环语句的结束
- 当count设置为1时,设置结束条件为cur.next==None(需要考虑链表为空的情况)一般不使用
- 当count设置为0时,设置结束条件为cur==None
- 当计数器count+1,cur指向下一个节点cur.next

- 最后返回计数器的值,即链表节点的个数,就是链表的长度
#单链表的长度def length(self):cur = self.__head#头节点所指赋给cur#创建count为0,可以不用考虑链表为空的情况count = 0 #创建一个计数器,来记录链表的长度while cur != None: #创建循环,并设置当游标指向尾结点的None时,停止循环count += 1cur = cur.next #当计数器加1,那么游标就指向下一个游标的next,即下个数的地址,就是下一个数return count #返回结果count
3.遍历链表
与length方法的算法类似,只不过要把指向的数给打印出来
- 把头节点所指的节点赋值给游标
- 创建循环
- 打印出游标的值elem
- 游标就指向节点游标的next
#遍历单链表def travel(self):#与length方法的算法类似,只是要把指向的数给打印出来cur=self.__head #游标指向头节点while cur != None: #创建循环,当游标指向尾结点None时,停止循环print(cur.elem)#遍历就是每次,打印出游标的值elemcur = cur.next#游标就指向节点游标的next,就是下一个数
4.尾部添加元素
- 传入元素值item
- 根据值创建节点
- 把__head所指的节点(头节点)赋值给游标

- 游标循环指向尾结点的next域

- 断开None,链接传入的节点

#传入元素值itemdef append(self,item):#创建节点node=Node(item)#创建游标cur=self.__head#用cur找到最后一个节点while cur.next != None:cur=cur.nextcur.next=node#传入节点
特殊情况
当链表为空时,cur=self.__head头节点为None,没有cur.next,发生错误。
所以要判断链表是为空if self.__head==None:
但是为了方便查看,我们通常调用方法is_empty(),来判断链表是否为空
- 创建节点
- 判断节点是否为空
- 为空:将节点传给头节点
- 不为空:将尾结点指向的None断开,指向node
def append(self,item):node=Node(item)#调用class Node类创建if self.is_empty(): #当节点为空,就把节点传给头节点node=self.__headelse: #否则找到尾结点,插入cur=self.__headwhile cur.next != None:cur=cur.nextcur.next=node
5.头部添加元素


- 创建节点
- 把__head指向的节点变成node指向
- __head指针指向创建的节点,作为头节点
def add(self,item):node=Node(item)node.next=self.__headself.__head=node
6.指定位置添加元素
在指定位置插入元素,我们需要用户传入,插入的位置以及插入的节点,所以定义的方法为:
基本思路:
- 定义一个pre指针,用于找到插入的位置
- 把pre指向__head所指向的头节点

- 传入一个节点,把节点的next区指向prev的next区

- 把pre的next指向这个节点

步骤思路:
- 创建pre指向头节点
- 创建计数器,来记录链表长度,并赋值为0
- 利用循环语句来移动指针pre
- 当计数器,即链表的个数等于插入位置的前一个数,就可以退出循环

- 当循环退出后,进行基本步骤的插入

class SingleLinkList(object):def __init__(self,node=None):self.__head=nodedef insert(self,pos,item):pre=self.__head#创建指针prenode=Node(item)#创建节点count=0while count<(pos-1):count+=1pre=pre.next#循环找pos-1node.next=pre.next #插入节点pre.next=node
特殊情况
空链表满足条件
当插入的数为负数pos<=0
- 调用头插法self.add()
当插入的数大于链表的长度(尾节点)pos>length()-1【0开始,长度为length-1】
- 注意位置≠链表长度【pos=length()-1:就代表时pos-1处断开节点】
- 调用尾插法self.append()
def insert(self,pos,item):pre=self.__head#创建指针prenode=Node(item)#创建节点count=0if pos<=0:self.add(item)elif pos>(self.length()-1):self.append(item)else:while count < (pos - 1):count += 1pre = pre.next # 循环找pos-1node.next = pre.next # 插入节点pre.next = node
7.查找元素
- 创建指针cur,遍历链表
当cur=None时结束循环【如果=cur.next,cur指向节点还没有比较】
def search(self,item):cur=self.__head()while cur != None:if cur.elem==item:#判断是否与要找的值相等return Trueelse:cur = cur.next#继续找return False#一直没找到
8.删除节点
基本思路:
- 创建两个指针,前驱pre指向None,cur后继指向头节点


- 前驱pre指向变化的cur,后继往后移,指向下一个节点cur.next


- 将节点的前一个节点的next指向节点的next域(后一个节点)

步骤思路:
- 创建指针cur指向头节点,pre指向空
- 找删除的节点,while循环遍历,只要cur节点不为None,就一直找
- 如果cur指向的值为传入的节点值,就按基本思路删除
- 否则就继续找下一个
def remove(self,item):cur=self.__headpre=Nonewhile cur != None:if cur.elem==item:pre.next=cur.nextbreak #删除完后,退出循环else:pre=curcur=cur.next
特殊情况
- 删除的是首节点_:直接
_head=cur.next

if cur.elem==item:if cur==self.__head:self.__head=cur.nextelse:pre.next=cur.nextbreak #删除完后,退出循环else:pre=curcur=cur.next
