数据结构学习----线性表的链式表示之循环单链表(Java实现)
2014-10-16 10:50 雪夜&流星 阅读(388) 评论(0) 编辑 收藏 举报线性表接口LList:
package com.clarck.datastructure.linked; /** * 线性表接口LList,描述线性表抽象数据类型,泛型参数T表示数据元素的数据类型 * * @author clarck * */ public interface LList<T> { /** * 判断线性表是否空 * @return */ boolean isEmpty(); /** * 返回线性表长度 * @return */ int length(); /** * 返回第i(i≥0)个元素 * @param i * @return */ T get(int i); /** * 设置第i个元素值为x * @param i * @param x */ void set(int i, T x); /** * 插入x作为第i个元素 * @param i * @param x */ void insert(int i, T x); /** * 在线性表最后插入x元素 * @param x */ void append(T x); /** * 删除第i个元素并返回被删除对象 * @param i * @return */ T remove(int i); /** * 删除线性表所有元素 */ void removeAll(); /** * 查找,返回首次出现的关键字为key元素 * @param key * @return */ T search(T key); }
单链表结点类:
package com.clarck.datastructure.linked; /** * 单链表结点类,T指定结点的元素类型 * * @author clarck * * @param <T> */ public class Node<T> { /** * 数据域,保存数据元素 */ public T data; /** * 地址域,引用后继结点 */ public Node<T> next; /** * 构造结点,data指定数据元素,next指定后继结点 * * @param data * @param next */ public Node(T data, Node<T> next) { this.data = data; this.next = next; } /** * 构造节点 */ public Node() { this(null, null); } /** * 返回结点元素值对应的字符串 */ @Override public String toString() { return this.data.toString(); } /** * 比较两个结点值是否相等,覆盖Object类的equals(obj)方法 */ @SuppressWarnings("unchecked") @Override public boolean equals(Object obj) { return obj == this || obj instanceof Node && this.data.equals(((Node<T>)obj).data); } }
线性表的链式表示之循环单链表:
package com.clarck.datastructure.linked; /** * 循环单链表类,实现线性表接口 * * @author clarck * * @param <T> */ public class CirSinglyLinkedList<T> implements LList<T> { /** * 头指针,指向循环单链表的头结点 */ public Node<T> head; /** * 默认构造方法,构造空循环单链表 */ public CirSinglyLinkedList() { this.head = new Node<T>(); this.head.next = this.head; } /** * 判断循环单链表是否空 */ @Override public boolean isEmpty() { return this.head.next == this.head; } /** * 返回循环单链表长度,单链表遍历算法,O(n) */ @Override public int length() { int i = 0; for (Node<T> p = this.head.next; p != this.head; p = p.next) { i++; } return i; } /** * 返回第i(≥0)个元素,若i<0或大于表长则返回null,O(n) */ @Override public T get(int i) { if (i >= 0) { Node<T> p = this.head.next; for (int j = 0; p != this.head && j < i; j++) p = p.next; if (p != this.head) return p.data; // p指向第i个结点 } return null; } /** * 设置第i(≥0)个元素值为x。若i<0或大于表长则抛出序号越界异常;若x==null,不操作。O(n) */ @Override public void set(int i, T x) { // 不能设置空对象 if (x == null) return; Node<T> p = this.head.next; for (int j = 0; p != this.head && j < i; j++) p = p.next; // p指向第i个结点 if (i >= 0 && p != this.head) p.data = x; else throw new IndexOutOfBoundsException(i + ""); // 抛出序号越界异常 } @Override public void insert(int i, T x) { // 不能插入空对象 if (x == null) return; // p指向头结点 Node<T> p = this.head; // 寻找插入位置 for (int j = 0; p.next != this.head && j < i; j++) { // 循环停止时,p指向第i-1结点或最后一个结点 p = p.next; } // 插入x作为p结点的后继结点,包括头插入(i<=0)、中间/尾插入(i>0) p.next = new Node<T>(x, p.next); } @Override public void append(T x) { insert(Integer.MAX_VALUE, x); } /** * 删除第i(≥0)个元素,返回被删除对象。若i<0或i大于表长,不删除,返回null。O(n) */ @Override public T remove(int i) { if (i >= 0) { Node<T> p = this.head; for (int j = 0; p.next != this.head && j < i; j++) { p = p.next; } if (p != null) { // 获得原对象 T old = p.next.data; // 删除p的后继结点 p.next = p.next.next; return old; } } return null; } /** * 删除单链表所有元素 Java将自动收回各结点所占用的内存空间 */ @Override public void removeAll() { this.head.next = this.head; } /** * 顺序查找关键字为key元素,返回首次出现的元素,若查找不成功返回null * key可以只包含关键字数据项,由T类的equals()方法提供比较对象相等的依据 */ @Override public T search(T key) { if (key == null) return null; for (Node<T> p = this.head.next; p != this.head; p = p.next) if (p.data.equals(key)) return p.data; return null; } /** * 返回循环单链表所有元素的描述字符串 */ @Override public String toString() { String str = "("; Node<T> p = this.head.next; // 遍历单链表的循环条件改变了 while (p != this.head) { str += p.data.toString(); if (p != this.head) str += ", "; // 不是最后一个结点时后加分隔符 p = p.next; } return str + ")"; } /** * 比较两条单链表是否相等 */ @SuppressWarnings("unchecked") @Override public boolean equals(Object obj) { if (obj == this) return true; if (obj instanceof SinglyLinkedList) { CirSinglyLinkedList<T> list = (CirSinglyLinkedList<T>) obj; return equals(this.head.next, list.head.next); } return false; } /** * 比较两条单链表是否相等,递归方法 * * @param p * @param q * @return */ private boolean equals(Node<T> p, Node<T> q) { return p == null && q == null || p != null && q != null && p.data.equals(q.data) && equals(p.next, q.next); } }
源码:https://github.com/clarck/DataStructure/tree/master/LinkedList/src/com/clarck/datastructure/linked
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本