论文阅读笔记(16):Doubly Stochastic Subspace Clustering,双重随机子空间聚类


Submitted on 30 Nov 2020 (v1), last revised 19 Apr 2021 (v2)

摘要

最先进的子空间聚类方法遵循两步过程,首先在数据点之间构建affinity矩阵,然后将谱聚类应用于该矩阵。对这些方法的大多数研究集中在产生affinity的第一步,这通常利用线性子空间的自表达特性,很少考虑产生最终的谱聚类步骤。此外,现有方法通常通过将特定或任意选择的后期处理步骤应用于自表达模型生成的affinity来获得谱聚类步骤中使用的最终affinity矩阵,这可能对整体聚类性能产生重大影响。在这项工作中,我们通过学习数据的自表达表示和谱聚类的规范化affinity矩阵来统一这两个步骤。在我们提出的模型中,我们将affinity矩阵约束为双重随机,这导致了一种原则性的affinity矩阵规范化方法,同时也利用了谱聚类中双重随机规范化的已知优点。我们开发了一个通用框架并推导了两个模型:一个模型联合学习自我表达表征和双重随机affinity,另一个模型依次求解。此外,我们利用问题中的稀疏性,为序列求解开发了一种快速的有效集方法,该方法能够在大型数据集上进行高效计算。实验表明,我们的方法在计算机视觉中的许多常见数据集上实现了最先进的子空间聚类性能。

简介

子空间聚类旨在将从低维线性(或仿射)子空间的并集近似提取的一组数据点聚类,其中每个线性(或仿射)子空间定义一个类(即给定类中的每个点位于同一子空间)。用于对一组n个数据点进行聚类的最常见的子空间聚类算法分两个阶段进行:

  1. 学习affinity矩阵 A ∈ R n × n A∈ R^{n×n} ARn×n,定义数据点对之间的相似性;
  2. 应用图聚类技术,如谱聚类,生成最终聚类。

可以说最流行的子空间聚类模型是通过利用线性(或仿射)子空间的“自表达”特性来构造affinity矩阵:任意点可以表示为同一子空间内其他点的线性组合。对于n个、d维的数据点组成的数据集 X ∈ R d × n X∈R^{d×n} XRd×n,这通常有以下形式的优化问题:

在这里插入图片描述
其中,第一个项捕获了自表达属性 X ≈ X C X≈XC XXC\第二项 θ θ θ C C C上的正则化项,用于鼓励给定点主要由其自身子空间中的其他点表示,并避免诸如 C = I C=I C=I之类的平凡解。一旦学习了 C C C,则通常通过对 C C C进行整流和对称化来构造最终的affinity矩阵 A A A,如 A = ( ∣ C ∣ + ∣ C ⊤ ∣ ) / 2 A=(| C |+|C^\top|)/2 A=(C+C)/2

然而,正如在图1中所示,许多子空间聚类方法需要在 C C C上进行特殊或不合理的后处期理过程才能实际工作。这些后期处理步骤用于规范化 C C C,以产生具有更好谱聚类性能的 A A A,但它们为模型添加了大量超参数,相关论文对此避而不谈。同样,众所周知,谱聚类的成功需要某种形式的拉普拉斯规范化,对于这一点,实践者同样可以选择多种规范化策略。

在这里插入图片描述
在本文中,我们提出了一个新的子空间聚类框架,它显式地连接了自表达、affinity规范化、和谱聚类步骤。我们为这个框架开发了新的可扩展方法,解决了与其他子空间聚类模型相关的问题,并且在经验上优于其他子空间聚类模型。我们首先讨论了成功的谱聚类所需要affinity的期望性质。具体来说,我们需要具有以下属性的affinity A A A

(A1) 为谱聚类进行良好的规范化。 我们应该更好地利用被输入谱聚类的 A A A的知识。

(C1) 稀疏性。 通过在 C C C上实施稀疏性,人们发现子空间聚类非常成功。设计了许多稀疏性增强方法,以确保affinity矩阵的非零项对应于属于同一子空间的点对。

(C2) 连通性。 A A A的潜在图中应该有足够多的边,以便同一子空间中的所有点都是连通的。因此,子空间聚类方法必须考虑稀疏性和连通性之间的权衡。

属性(C1)和(C2)已得到了很好的研究,并且可以在自表达的 C C C上实施,因为使用这些属性对 C C C进行校正和对称化可以保持这些属性。但是属性(A1)必须对 A A A强制执行,并且主要通过特别的后期处理方法来处理。在研究(A1)时,我们首先考虑 A ≥ 0 A≥ 0 A0,因为affinity的非负性对于解释性和与谱聚类理论的一致性是必要的。除此之外,谱聚类还受益于在affinity矩阵中的行和列具有相同的尺寸,谱聚类的许多形式的拉普拉斯规范化使行和/或列具有相似的尺度。特别地,谱聚类文献中确立的一种规范化形式是约束行和列具有单位 ℓ 1 \ell_1 1范数。由于 A A A另外被限制为非负,这相当于要求 A A A的每行和每列和为1,从而产生限制affinity A A A位于双随机矩阵凸集的约束:

在这里插入图片描述
双随机矩阵已被彻底研究用于谱聚类,双随机规范化已被证明可显著改善谱聚类的性能。此外,双随机矩阵对最广泛使用的拉普拉斯归一化类型是不变的,这消除了选择拉普拉斯归范化方案的需要。此外,文献表明,各种拉普拉斯归范化方案可被视为试图在某些距离度量下用双随机矩阵逼近给定的affinity矩阵。

除了对谱聚类(A1)进行良好规范化之外,双随机矩阵族还可以满足(C1)和(C2)性质。我们提出的方法将通过可解释的参数来控制稀疏性-连通性权衡,并且我们在实践中学习到一种非常稀疏的方法。此外,由于行和为1的约束,双随机矩阵具有一定程度的连接性,这禁止了所有零行的解(在其他子空间聚类方法中可能发生)。凸性 Ω n Ω_n n和所学到 A A A的稀疏性使我们能够开发新的可伸缩双随机投影算法,从而开发具有双随机affinity的子空间聚类的可伸缩方法。

文章贡献

在这项工作中,我们开发了一个框架,通过建立一个模型,将子空间聚类的自表达表示步骤与谱聚类步骤统一起来,该模型联合求解自表达表示 C C C和双随机affinity矩阵 A A A虽然我们的一般模型是非凸的,但我们提供了一种凸relax,可以证明它接近于非凸模型,并且可以通过一种线性化的交替方向乘子法ADMM来解决。通过更仔细的分析,我们还可以制定一种序列算法来快速计算近似解,在该算法中,我们首先有效地学习自表达矩阵,然后通过带正则化的最优运输问题拟合双随机矩阵。我们利用问题中固有的稀疏性,开发了一种可扩展的有效集方法,用于在该序列模型中进行计算。最后,我们通过在各种标准子空间聚类数据集上的实验验证了我们的方法。

相关工作

自表示模型和affinity学习

试图在子空间聚类中统一自表达和谱聚类步骤的现有方法包括:结构化SSC(李老师那篇阅读笔记),它联合学习自表达表示和二进制聚类矩阵;以及块对角表示和SC-LALRG,它们共同学习了谱聚类的自我表达表示和受限affinity。然而,所有这些方法都是非凸的,需要迭代优化方法,并且需要在每次迭代中进行昂贵的谱计算。因此,它们的可伸缩性非常有限。相比之下,我们的方法具有凸公式,并且我们可以使用我们开发的算法非常高效地计算真极小值。

双重随机聚类

双随机约束往往用于当输入的affinity已知时的标准谱聚类方法,但它们没有像子空间聚类中所期望的那样,用于直接学习自表达表示的affinity矩阵。

具体地,Zass和Shashua通过将标准谱聚类应用于距离输入affinty矩阵的Frobenius范数(即 ∣ ∣ X ∣ ∣ F = ∑ i ∑ j x i j 2 ||X||_F=\sqrt{\sum_i\sum_jx_{ij}^2} XF=ijxij2 )最近的双随机矩阵,发现了强大的性能。此外,还研究了受秩约束的输入affinity矩阵的双随机近似。此外,Landa等人证明,通过对角矩阵缩放对泛高斯核矩阵进行双重随机规范化,对数据点上的异质(heteroscedastic)加性噪声具有鲁棒性。

据我们所知,只有一个子空间聚类方法利用了双重随机约束,但它们实施了非常昂贵的半正定约束,使用了特殊的非凸后处理,并且不直接将谱聚类应用于双重随机矩阵。相比之下,我们开发了具有原则性凸公式的可伸缩方法,在应用谱聚类之前不需要进行后处理。

可伸缩的子空间聚类方法

现有的方法或使子空间聚类可伸缩的方法利用自表达表示中的稀疏性,利用最终affinity中的结构,或使用贪婪启发式算法计算子空间聚类。我们的可扩展方法能够利用自表达表示和构造的affinity稀疏性,易于并行化(允许简单快速的GPU实现),并且完全凸,不使用贪婪的启发式。

双重随机子空间聚类

在本节中,我们将进一步详细介绍学习子空间聚类的双随机affinity的动机。然后,我们提出了两个具有双重随机affinity的子空间聚类模型。我们的J-DSSC模型联合学习自表达矩阵和双随机affinity,而我们的A-DSSC模型是一个快速近似,先求解自表达矩阵,然后是一个双随机affinity来逼近它。

双随机affinity的优点

现有的子空间聚类方法,如SSC、LRR、EDSC和深度子空间聚类网络(DSC-Net)需要各种特殊的后处理方法,以在某些数据集上实现强大的聚类性能。例如,最近的研究表明,如果从DSC网络中删除特殊的后处理步骤,则性能会大幅下降——性能不比简单的方法好,远远低于最先进的方法。常见的后处理步骤包括仅保留 C C C的每一列的前 l l l项、规范化 C C C的列或使用基于SVD的后处理,每一步都引入额外的超参数和自由度。同样,还需要选择要使用的特定类型的拉普拉斯归一化[43]。

为了更好地将自我表达步骤与后续的谱聚类步骤联系起来,并避免需要特殊的后处理方法,我们提出了一个直接学习affinity A A A的框架,affinity A A A已经具有谱聚类所需的属性A1、C1和C2。限制 A ∈ Ω n A∈Ω_n An在双随机矩阵的凸集中实现了这些目标,同时允许高效的计算。

如引言中所述,双随机矩阵已经是非负的,因此我们不需要取某些计算矩阵的绝对值。此外,双随机矩阵的每一行和每一列相加为1,因此它们在 ℓ 1 \ell_1 1范数中具有相同的比例——无需通过缩放行或列来进行后处理。

重要的是,对于A1属性,双随机矩阵对于谱聚类中使用的大多数形式的拉普拉斯规范化是不变的。例如,对于对称affinity矩阵 A A A的行之和 D = d i a g ( A ⋅ 1 ) D=diag(A\cdot1) D=diag(A1),常用的拉普拉斯变量有:未规范化的拉普拉斯矩阵 D − A D-A DA、规范化的拉普拉斯矩阵 I − D − 1 / 2 A D − 1 / 2 I-D^{-1/2}AD^{-1/2} ID1/2AD1/2、随机游走拉普拉斯矩阵 I − D − 1 A I-D^{-1}A ID1A。而对于双随机矩阵,矩阵的行之和满足 D = I D=I D=I,故所有的规范化变量都等价于这种方式得到的拉普拉斯矩阵 I − A I-A IA

对于子空间聚类,许多类型的正则化和约束用于提供稀疏性(C1)和连通性(C2)。即,当 x i x_i xi x j x_j xj属于不同的子空间时,他们希望 A i j A_ij Aij较小或为0(稀疏性);而对于足够多的点对 ( i , j ) (i,j) (i,j)当它们来自同一子空间时,又希望是非零的(连通性)。我们的模型学习的双随机矩阵可以调整以达到任何期望的稀疏度水平。此外,由于每一行的总和必须为1,因此双随机affinity可以保证一定程度的连通性。这与SSC、EnSC和SSC-OMP等每次计算一列表示的方法不同,在这些方法中,可能某个点从不用于其他点的自我表达表示。

联合学习:J-DSSC

在共同学习自表达矩阵和双重随机affinity时,我们基于一般的正则化自表达形式。除了学习自表达矩阵 C C C,我们还希望学习双随机affinity矩阵 A ∈ Ω n A∈Ω_n An自表达公式。自我表达公式(粗略地)将 ∣ C i j ∣ |C_{ij}| Cij建模为 x i x_i xi x j x_j xj位于同一子空间中的似然性,因此我们希望我们的affinity A A A规范化到接近 ∣ C ∣ | C | C(例如在将 A A A缩放一个常数以匹配 ∣ C ∣ |C| C)之后,我们用罚函数 Θ ( ⋅ , ⋅ ) Θ(·,·) Θ(,)将其合并。因此,我们有:

在这里插入图片描述

本来这个优化是用来计算 C C C的, A A A往往后处理计算得到。在这同时优化 C C C A A A,与其它的方法不同之处主要就在于第三项的罚函数将 A A A ∣ C ∣ |C| C匹配,以及将 A A A约束到双随机凸集 Ω n 中 \Omega_n中 Ωn

我们的框架是通用的,并且可以与例如低秩(low-rank)罚函数一起使用,我们选择了一种简单的 ℓ 1 + ℓ 2 \ell_1+\ell_2 1+2的混合正则化,这是有效的并有快速算法。对于 Θ Θ Θ,我们使用 ℓ 2 \ell_2 2距离惩罚,因为affinity矩阵在双随机矩阵上的 ℓ 2 \ell_2 2投影通常会提高谱聚类性能,并产生理想的稀疏性特性。因此,我们的模型采用的优化问题的形如:
在这里插入图片描述
其中 η \eta η为各个正则化项的trade-off超参数。

因为C到A的损失中的 ∣ C ∣ |C| C项,目标(4)并不是凸的。为缓解这个问题,我们通过将自表达矩阵 C C C分解为两个非负矩阵 C p , C q ≥ 0 C_p, C_q≥ 0 Cp,Cq0来缓解这个问题,使 C p − C q Cp−Cq CpCq近似地为 C C C C p + C q Cp+Cq Cp+Cq近似为 ∣ C ∣ |C| C(如果 C p C_p Cp C q C_q Cq的非零支撑集不重叠,则这种近似是精确的)。因此,我们的凸模型如下所示:

在这里插入图片描述
其中 R ≥ 0 , d i a g = 0 n × n \mathbb R^{n\times n}_{\geq 0, diag=0} R0,diag=0n×n n × n n\times n n×n的实矩阵的集合,并要求这些矩阵非负且对角元素为零。这个问题现在是凸的,可以有效地求解全局最优。我们将该模型称为联合双随机子空间聚类(J-DSSC)。

命题 1: 假设目标(5)的最优解为 ( C p ∗ , C q ∗ , A ∗ ) (C^*_p,C^*_q,A^*) (Cp,Cq,A)

  1. 如果 η 1 η 2 ≤ η 3 η1η2≤ η3 η1η2η3,则当取 C = C ∗ p − C q ∗ C=C*_p-C^*_q C=CpCq时,relax的(5)的解与(4)的解相同。特别地, C ∗ p C*_p Cp C q ∗ C^*_q Cq的支撑集是不相交的。
  2. 如果 η 1 η 2 > η 3 η1η2>η3 η1η2>η3,则 C ∗ p C*_p Cp C q ∗ C^*_q Cq的支撑集可能存在重叠。对于任何 ( C ∗ p ) i j > 0 (C*_p)_{ij}>0 (Cp)ij>0 ( C ∗ q ) i j > 0 (C*_q)_{ij}>0 (Cq)ij>0的点对 ( i , j ) (i,j) (i,j),满足:
    在这里插入图片描述

序列算法近似:A-DSSC

在这里插入图片描述

从这种形式可以看出,对于 A = I A=I A=I的非信息性affinity初始化,对 C C C的最小化实际上是弹性网络子空间聚类的形式:
在这里插入图片描述
同样对于给定的 C C C,可以观察到上述问题是二次正则化最优运输问题的特例[4,28]:

在这里插入图片描述
因此, η 2 η_2 η2用于控制A的正则化,较小的 η 2 η_2 η2鼓励更稀疏的 A A A,较大的 η 2 η_2 η2鼓励更密集和更均匀的 A A A。特别地,当 η 2 → 0 η_2→ 0 η20时,目标(9)接近线性分配问题,该问题具有置换矩阵解(即最大稀疏解)[36,17]。相反,如 η 2 → ∞ η_2→ ∞ η2, 最优解是稠密连通的,并且该解逼近一致矩阵 1 n 1 1 ⊤ \frac{1}{n}11^\top n111

因此,我们考虑交替最小化来获得 C C C A A A的近似解。具体地,我们首先初始化 A = I A= I A=I,并求解目标(8)得到 C C C;然后保持 C C C不变,我们求目标(9)得到 A A A。将该问题的解作为最终的affinity A A A,我们得到了J-DSSC的一步近似,我们称之为近似双随机子空间聚类(A-DSSC)2。对于该模型,我们开发了一个快速算法,实验表明,A-DSSC很好地逼近了J-DSSC的优化问题。

除了用近似联合优化目标(5),A-DSSC还可以解释为某些子空间聚类方法的后处理方法,如SSC、EnSC和LSR,如目标(8)所示。我们不是任意选择如何对 A A A进行后处理并形成规范化的拉普拉斯算子,而是将 A A A视为双重随机——这提供了一种生成affinity A A A的原则性方法,适合从良好的凸优化问题(9)进行谱聚类规范化。

优化步骤与实现

联合求解 J-DSSC

为了有效地求解 J-DSSC的目标(5),我们开发了一种线性化ADMM算法。我们通过引入附加变量来重新参数化问题,并在增广拉格朗日上迭代地最小化,以及在对偶变量上采取对偶上升。

近似求解 A-DSSC

求解C
近似模型A-DSSC可以比J-DSSC更有效地求解。对于给定 A A A C C C在(8)上的最小化问题可以通过某些可伸缩的子空间聚类算法来解决。一般而言,它相当于为此开发了可伸缩算法EnSC。同样,在 η 1 > 0 , η 3 = 0 η_1>0,η_3=0 η1>0,η3=0的情况下,它等价于LSR,可以通过单个 n × n n×n n×n线性系统求解来计算。

求解A
先前的工作主要是通过原始计算对目标(9)的双随机投影,但我们将通过对偶来解决它。对偶给出了两个向量 α , β ∈ R n α,β∈\mathbb R^n α,βRn上的无约束优化问题,它更容易求解,因为它消除了原式的耦合约束。对偶允许显著更快的计算,在某些设置下有超过一个数量级的改进。此外,对偶允许我们开发一个高度可扩展的活动集方法,该方法还允许一个简单的GPU实现——从而允许比现有方法更进一步的加速。对偶采用以下形式:

在这里插入图片描述

其中 [ ⋅ ] + [\cdot]_+ []+表示半波整流,即 [ x ] + = m a x 0 , x [x]_+=max{0,x} [x]+=max0,x,作用于作用于矩阵里的每一个元素(entry-wise,元素级)。最优矩阵 A A A可以根据这两个向量恢复:
在这里插入图片描述
然后使用 L − B F G S L-BFGS LBFGS求解 α , β α,β α,β

A-DSSC的可伸缩有效集方法

虽然A-DSSC可以比J-DSSC更有效地计算,但双随机投影步骤(9)仍然需要 O ( n 2 ) \mathcal O(n^2) O(n2)的复杂度来计算目标(10)与次梯度。这限制了它对较大数据集的直接适用性。我们利用了在我们选择的参数区域中最优 A A A的稀疏性,并发展了一种有效集方法来计算(9)中的双随机投影。

S ∈ { 0 , 1 } n × n S\in\{0,1\}^{n\times n} S{0,1}n×n为二值支撑集矩阵, S c S^c Sc S S S的补集。考虑:
在这里插入图片描述
同样,我们使用对偶开发了一个高效的求解器:

在这里插入图片描述
对偶目标函数及其次梯度可以在 O ( ∣ S ∣ ) \mathcal O(|S|) O(S)时间内计算,其中 ∣ S ∣ |S| S S S S中非零的数量。在实践中,我们往往只需要比 n 2 n^2 n2小得多的 ∣ S ∣ |S| S,因此效率大幅提高。同样,我们只需要计算在支撑集 S S S中的 C C C的元素;这些元素可以以较低的内存成本进行预计算和存储,以实现更快的L-BFGS迭代。特别是,这允许在大型数据集中应用LSR(least square regression,即 η 3 = 0 η_3=0 η3=0);即使在LSR 中 C 中C C是稠密的并且需要 O ( n 2 ) \mathcal O(n_2) O(n2)内存,我们也只需要计算 C ⊙ S C\odot S CS:这可以通过矩阵闭式求解有效地完成,并且将所需内存缩减为 O ( ∣ S ∣ ) \mathcal O(|S|) O(S)。如上所述,目标和次梯度计算可以很容易地在GPU上实现并允许进一步的加速。

对于对偶解 ( α ∘ , β ∘ ) (\alpha_\circ,\beta_\circ) (α,β),最优解为 1 η 2 [ ∣ C ∣ − α ∘ 1 ⊤ − 1 β ∘ ⊤ ] ⊙ S \frac{1}{\eta_2}[|C|-\alpha_\circ1^\top-1\beta_\circ^\top]\odot S η21[Cα11β]S。如果具有无约束支撑集的affinity A ∘ = 1 η 2 [ ∣ C ∣ − α ∘ 1 ⊤ − 1 β ∘ ⊤ ] + A_\circ=\frac{1}{\eta_2}[|C|-\alpha_\circ1^\top-1\beta_\circ^\top]_+ A=η21[Cα11β]+是双重随机的,那么 A ∘ A_\circ A 是(9)的最优解。因此,如果我们迭代地更新初始支撑集 S S S,则 A ∘ A_\circ A的行和列和将提供达到最佳的停止标准。另一方面,如果 A ∘ A_\circ A不是双重随机的,那么不受限问题(9)的真极小值 A A A的支撑集不包含在 s u p p ( S ) supp(S) supp(S)中。在这种情况下,我们将按 s u p p ( S ) ← s u p p ( S ) ∪ s u p p ( A ∘ ) supp(S)\leftarrow supp(S)\cup supp(A_\circ) supp(S)supp(S)supp(A)更新支撑集 S S S

在这里插入图片描述

因此,我们有一个算法,它初始化一个支持,然后迭代地求解受限支撑集的问题,直到不受限的affinity A ∘ A_\circ A 是双重随机的。算法2对此进行了形式化。我们可以证明:

命题2: 算法2一定能在有限迭代次数内求解得到的最优解 A A A

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Definition: A circular doubly linked list is a data structure that consists of a sequence of nodes, where each node contains a value, a reference to the next node, and a reference to the previous node in the sequence. The last node in the list points to the first node, creating a circular structure. Detailed study (explanation): A circular doubly linked list is similar to a doubly linked list, but with the added feature of being circular. This means that the last node in the list points back to the first node, creating a loop. This allows for more efficient traversal of the list in both directions, as well as easier implementation of certain algorithms. Applications: Circular doubly linked lists are useful in situations where a list needs to be traversed in both directions, such as in a music playlist where the user can skip forwards and backwards through songs. They can also be used in certain algorithms, such as the Josephus problem, where a group of people are arranged in a circle and every nth person is eliminated until only one person is left. Operations: Some common operations that can be performed on a circular doubly linked list include: 1. Insertion: Adding a new node to the list at a specific position. 2. Deletion: Removing a node from the list. 3. Traversal: Moving through the list in either direction, starting at a specific node. 4. Search: Finding a specific node in the list based on its value. Program implementation: A circular doubly linked list can be implemented using a Node class that contains the value, a reference to the next node, and a reference to the previous node. The list itself can be represented by a head node that points to the first node in the list. Java/C/C++ source code to perform operation: Here's some Java code that demonstrates how to perform various operations on a circular doubly linked list: ``` public class Node { int value; Node next; Node prev; public Node(int value) { this.value = value; this.next = null; this.prev = null; } } public class CircularDoublyLinkedList { Node head; public CircularDoublyLinkedList() { this.head = null; } public void insert(int value, int position) { Node newNode = new Node(value); if (head == null) { head = newNode; head.next = head; head.prev = head; } else { Node current = head; for (int i = 1; i < position; i++) { current = current.next; } newNode.next = current.next; newNode.prev = current; current.next.prev = newNode; current.next = newNode; } } public void delete(int value) { if (head == null) { return; } Node current = head; do { if (current.value == value) { current.prev.next = current.next; current.next.prev = current.prev; if (current == head) { head = current.next; } return; } current = current.next; } while (current != head); } public void traverseForward() { if (head == null) { return; } Node current = head; do { System.out.print(current.value + " "); current = current.next; } while (current != head); System.out.println(); } public void traverseBackward() { if (head == null) { return; } Node current = head.prev; do { System.out.print(current.value + " "); current = current.prev; } while (current != head.prev); System.out.println(); } public Node search(int value) { if (head == null) { return null; } Node current = head; do { if (current.value == value) { return current; } current = current.next; } while (current != head); return null; } } ``` Output-screenshot: Here's an example of how to use the above code to perform various operations on a circular doubly linked list: ``` CircularDoublyLinkedList list = new CircularDoublyLinkedList(); list.insert(1, 1); list.insert(2, 2); list.insert(3, 3); list.insert(4, 4); list.traverseForward(); // Output: 1 2 3 4 list.traverseBackward(); // Output: 4 3 2 1 list.delete(2); list.traverseForward(); // Output: 1 3 4 Node node = list.search(3); System.out.println(node.value); // Output: 3 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值