单链表的基础操作与常见算法实现

本文介绍了单链表的基本概念、Python实现以及常见的操作,包括获取链表长度、插入和删除节点,以及单链表的倒序和特定值的删除算法。
摘要由CSDN通过智能技术生成

前言

        最近在编程时觉得自己在数据结构与算法上有很大不足急需弥补一下,决定总该写点东西了。便复习了一下链表的基础知识,在这里分享一下自己的心得。

概述

        单链表是一种基础的数据结构,虽然在平时的开发中较少用到,但我个人而言,学习单链表是从数据结构入门的一个好开端,毕竟是比较简单,而且在算法代码的练习中,总能不知不觉地感受到指针与内存地址的存在。

        链表是一种物理存储上非连续,数据元素的逻辑顺序通过链表中的指针链接次序,实现的一种线性存储结构。链表由一系列的节点组成,节点动态生成。在单链表中,单个节点由存储元素的数据域与指向下一个节点地址的指针组成。

        对单链表的操作即建立在对链表中节点的指针操作。(在这里只演示不带哨兵模式情况下的单链表)

节点例:(python为例子):

class SinglyNode:
    def __init__(self, value=0, next=None):
        self.value = value #数据域
        self.next = next    #指向下一个节点地址的指针

    def __str__(self):
        return str(self.value)
public class SinglyNode {
    private Object value;//数据域
    private Object next;//指向下一个节点地址的指针

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

    public Object getNext() {
        return next;
    }

    public void setNext(Object next) {
        this.next = next;
    }
}

 单链表例子:

class SinglyLinkedList:

    #头结点指针
    head = None

如上代码,一个单链表最基础的是一个头结点

基础操作

        1.获取单链表长度

        核心思想即不断遍历链表节点,每切换一个节点即链表长度+1

    def getLinkLength(self):
        curent = self.head
        count = 0
        while curent != None:
            count += 1
            curent = curent.next
        return count

        2.获取尾部一个节点

        核心思想即遍历到最后一个节点时,将该节点返回即可

    def getLastNode(self):
        if not self.head: #当链表为空时
            return None  # 链表为空,返回 None
        current = self.head
        while current.next:
            current = current.next
        return current

        3.获取指定下标的节点

        核心思想用一个整数作为计数器来确定要返回的节点

    def getIndexNode(self,index):
        if self.head == None: #当链表为空时
            return None  # 链表为空,返回 None
        point = self.head
        count = 0
        while point != None:
            if count == index:
                return point
            point = point.next
            count += 1
        raise IndexError("数组越界")

        4.头插法和尾插法插入数据

        实际上,头插法在各种插入的的方式中是最高的了,尾插法即找到最后的节点,然后将该节点的指针指向待插入的节点

    #以头插法向单链表中插入数据
    def addFirstNode(self, node):
        if self.head is None:
            self.head = node
        else:
            node.next = self.head
            self.head = node

    #尾部插入节点
    def addLastNode(self, node=None):
        point = self.getLastNode() #获取最后位置的节点
        if point is None:
            raise IndexError("链表为空")
        point.next=node

        5.插入节点

        通过计数器来确定插入的位置

    def insert(self, index, node):
        length = self.getLinkLength()
        if not self.head: #当链表为空时
            return None  # 链表为空,返回 None
        if index == 0:
            self.addFirstNode(node)
            return
        pre = self.head
        count = 0
        while pre != None:
            if count == index-1:
                break
            pre = pre.next
            count += 1
        next=pre.next #下一跳的节点
        node.next = next
        pre.next = node
        return True

        6.删除头结点和尾结点

#删除头结点
    def removeFirstNode(self):
        curent = self.head.next
        self.head.next = None
        self.head = curent

    #删除尾部节点
    def removeLastNode(self):
        if self.head is None:
            return False
        length = self.getLinkLength()
        if length == 1:
            self.head = None
            return True

        pre = self.getIndexNode((length-2))
        pre.next = None

7.删除节点

找到下标节点,删除该节点

#删除某个节点
    def remove(self,index):
        length = self.getLinkLength()
        if length == 0 or length-1 < index:
            raise ValueError("长度越界了")
        if index == 0:
            self.removeFirstNode() #删除头结点
        if index == length-1: #最后的恶一个节点
            self.removeLastNode()
        pre = self.getIndexNode(index-1)
        curent = pre.next
        next = pre.next.next
        curent.next = None
        pre.next = next

        8.得到链表的数组

        在这里得到的数组使用的地址不是原链表的节点对象地址,即互不影响

#遍历链表得到对象数组
    def loop(self):
        nodeNums = []
        point = self.head
        while point != None:
            nodeNums.append(SinglyNode(point.value))
            point = point.next
        return nodeNums

常见算法

        1.单链表倒序

        核心思想就是桑连续的指针prevr,curent,next,从头到尾循环将指针调转方向

    def reversalList(self):
        length = self.getLinkLength()
        if length == 0 or length == 1:
            return
        prver = None
        current = self.head

        while current is not None:
            nextNode = current.next
            # 将当前节点的下一个节点指向前一个
            current.next = prver
            prver = current
            current = nextNode
        self.head = prver

        2.删除特定的值

        核心思想就是两个一前一后的指针p,q。p在后面记录位置,q在前面探测是否可以删除

    def removeNode(self,node):
        if self.head is None:
            raise ValueError("链表为NUll")
        if self.head.value == node.value:
            if self.head.next != None:
                next = self.head.next
                self.head.next = None
                self.head = next
            else:
                self.head = None
        #给p,q赋予初始位置
        p = self.head
        q = self.head.next
        # 只要q不为None即一直往后走
        while q != None:
            if q.value == node.value: #当q就是要删除的位置时
                q = q.next
                p.next.next = None
                p.next = q
            else:
                q = q.next
                p = p.next
        # 完成

        3.删除倒数的节点

        即从后面开始数的节点开始删除,比如1就删除最后一个,2就是删除倒数第二个,可以使用递归的方式去探找最后一个节点

    def removeNthFromEndRecursion(self,index,point,preve):
        if index < 1:
            return
        current = point
        #判断是不是最后尾部的节点
        if current.next == None:
            if index == 1:
                preve.next = None
            return 1
        else:
            result = self.removeNthFromEndRecursion(index,current.next,current)
            if result+1 == index:
                if preve == None:#当删除的是第一个节点时走这个逻辑
                    self.head = point.next
                    point.next = None
                else:
                    point = point.next
                    preve.next.next = None
                    preve.next = point
            return result+1

(待更新)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邻家小妹妹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值