首页 > 代码库 > 双向链表模拟
双向链表模拟
我们熟悉了java单向链表的模拟,现在我就必须开始双向链表的模拟的.
1.基础结构对象DuLNode
public class DuLNode {
private Object data;// 存放结点值
private DuLNode prior; // 前驱结点的引用
private DuLNode next; // 后继结点的引用
public DuLNode() {// 无参数时的构造函数
this(null);
}
public DuLNode(Object data) {// 构造值为data的结点
this.data = http://www.mamicode.com/data;
this.prior = null;
this.next = null;
}
public Object getData() {
return data;
}
public DuLNode getNext() {
return next;
}
public DuLNode getPrior() {
return prior;
}
public void setData(Object data) {
this.data = http://www.mamicode.com/data;
}
public void setNext(DuLNode next) {
this.next = next;
}
public void setPrior(DuLNode prior) {
this.prior = prior;
}
}
2.双向链表操作接口类
public interface IList {
public void clear(); // 将一个已经存在的线性表置成空表
public boolean isEmpty(); // 判断当前线性表中的数据元素个数是否为0,若为0则函数返回true,否则返回false
public int length(); // 求线性表中的数据元素个数并由函数返回其值
public Object get(int i) throws Exception;// 读取到线性表中的第i个数据元素并由函数返回其值。其中i取值范围为:0≤i≤length()-1,如果i值不在此范围则抛出异常
public void insert(int i, Object x) throws Exception;// 在线性表的第i个数据元素之前插入一个值为x的数据元素。其中i取值范围为:0≤i≤length()。如果i值不在此范围则抛出异常,当i=0时表示在表头插入一个数据元素x,当i=length()时表示在表尾插入一个数据元素x
public void remove(int i) throws Exception;// 将线性表中第i个数据元素删除。其中i取值范围为:0≤i≤length()- 1,如果i值不在此范围则抛出异常
public int indexOf(Object x);// 返回线性表中首次出现指定元素的索引,如果列表不包含此元素,则返回 -1
public void display();// 输出线性表中的数据元素
}
3. 双向循环链表及其基本操作
public class DuLinkList implements IList{
private DuLNode head;// 双向循环链表的头结点
// 双向链表的构造函数
public DuLinkList() {
head = new DuLNode(); //初始化头结点
head.setPrior(head);//初始化头结点的前驱和后继
head.setNext(head);
}
//n为该双向链表的元素个数
public DuLinkList(int n) throws Exception {
this();
Scanner sc=new Scanner(System.in);// 构造用于输入的对象
for (int j = 0; j < n; j++)
insert(j,sc.next());//生成新结点,插入到表头
}
// 在双向循环链表的第i个数据元素之前插入一个值为x的数据元素,i等于表长时,p指向头结点;i大于表长时,p=NULL。
// 其中i取值范围为:0≤i≤length()。当i=0时表示在表头插入一个数据元素x,当i=length()时表示在表尾插入一个数据元素x
public void insert(int i, Object x) throws Exception {
DuLNode p = head.getNext();// 初始化,p指向首结点,j为计数器
int j = 0;
while (p!=null && j < i) {// 寻找插入位置i
p = p.getNext();// 指向后继结点
j++;// 计数器的值增1
}
if (j>i && p==null)// i小于0或者大于表长
{
throw new Exception("插入位置不合理");
}
//生成新结点
DuLNode s = new DuLNode(x);
//i位置之前
s.setNext(p);
s.setPrior(p.getPrior());
p.getPrior().setNext(s);
p.setPrior(s);
}
// 将双向循环链表中第i个数据元素删除。其中i 取值范围为:0≤i≤ength()-1
public void remove(int i) throws Exception {
DuLNode p = head.getNext();// 初始化,p指向首节点结点,j为计数器
int j = 0;
while (p!=head && j < i) {// 寻找删除位置i
p = p.getNext();// 指向后继结点
j++;// 计数器的值增1
}
if (j>i) // i小于0或者大于表长减1
throw new Exception("删除位置不合理");// 输出异常
p.getPrior().setNext(p.getNext());
p.getNext().setPrior(p.getPrior());
}
// 将一个已经存在的双向循环链表置成空表
public void clear() {
head.setPrior(head);
head.setNext(head);
}
// 判断当前双向循环链表是否为空
public boolean isEmpty() {
return head==head.getNext();
}
// 读取双向循环链表中的第i个数据元素
public Object get(int i) throws Exception {
DuLNode p = head.getNext();// 初始化,p指向首结点,j为计数器
int j = 0;
while (p!=head && j < i) {// 从首结点向后查找,直到p指向第i个元素或p指向头结点
p = p.getNext();// 指向后继结点
++j;// 计数器的值增1
}
if (j > i || p==head) { // i小于0或者大于表长减1
throw new Exception("第" + i + "个元素不存在");// 输出异常
}
return p.getData();// 返回元素p
}
// 求双向循环链表中的数据元素个数并由函数返回其值
public int length() {
DuLNode p = head.getNext();// 初始化,p指向首结点,length为计数器
int length = 0;
while (p!=head) {// 从首结点向后查找,直到p指向头结点
p = p.getNext();// 指向后继结点
length++;// 长度增1
}
return length;
}
// 在双向循环链表中查找值为x的元素,如果找到,则函数返回该元素在线性表中的位置,否则返回-1
public int indexOf(Object x) {
DuLNode p = head.getNext();// 初始化,p指向首结点,j为计数器
int j = 0;
while (p!=head && !p.getData().equals(x)) {// 从链表中的首结点元素开始查找,直到p.getData()指向元素x或到达链表的表尾
p = p.getNext();// 指向下一个元素
j++;// 计数器的值增1
}
if (p!=head)// 如果p指向表中的某一元素
return j;// 返回x元素在顺序表中的位置
else
return -1;// x元素不在顺序表中
}
//双向链表输出
public void reverse()
{
DuLNode p=head.getNext();
head.setNext(null);
DuLNode q=null;
while(p!=head)
{
//保存下一个值
q=p.getNext();
p.setNext(head.getNext());
p.setPrior(head);
head.setNext(p);
p=q;
}
}
public void display() {
DuLNode node = head.getNext();// 取出带头结点的双向链表中的首结点
while (node!=head && node!=null) {
System.out.print(node.getData() + " ");// 输出数据元素的值
node = node.getNext();
}
System.out.println();
}
public DuLNode getHead() {
return head;
}
public void setHead(DuLNode head) {
this.head = head;
}
}
小结:假如是循环链表呢?大家不妨自己写写,我这里提供一个带头的循环链表的代码如下:
public class CircleLinkList implements IList{
//头节点
public Node head;
// 自连接的循环链表
public CircleLinkList() {
head = new Node();
head.setNext(head);
}
public Node getHead() {
return head;
}
public void setHead(Node head) {
this.head = head;
}
public CircleLinkList(int n,boolean order)
{
this();//初始化
if(order)
{
create1(n);//用尾插入法插入链表
}
else
{
create2(n);//用头插法逆位序建立单链表
}
}
//用尾插入法插入链表
public void create1(int n)
{
//输入数据
Scanner sc=new Scanner(System.in);
for(int i=0;i<n;i++)
{
try {
this.insert(this.length(),sc.next());
} catch (Exception e) {
e.printStackTrace();
}
}
}
//用头插法逆位序建立单链表
public void create2(int n)
{
//输入数据
Scanner sc=new Scanner(System.in);
for(int i=0;i<n;i++)
{
try {
this.insert(0,sc.next());// 生成新结点,插入到表头
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 将一个已经存在的带头结点的循环单链表置成空表
public void clear() {
head.setNext(head);//清空链表
}
// 判断当前带头结点的循环单链表是否为空
public boolean isEmpty() {
return head.getNext().equals(head);
}
// 求带头结点的循环单链表中的数据元素个数并由函数返回其值
public int length() {
//取得首节点
Node p=head.getNext();
int length=0;
while(p!=head)
{
p=p.getNext();
length++;
}
return length;
}
// 读取带头结点的循环单链表中的第i个数据元素
public Object get(int i) throws Exception {
Node p = head.getNext();// 初始化,p指向首结点,j为计数器
int j = 0;
while (p!=head && j < i) {// 从首结点向后查找,直到p指向第i个元素或p指向头结点
p = p.getNext();// 指向后继结点
++j;// 计数器的值增1
}
if (j > i || p==head) { // i小于0或者大于表长减1
throw new Exception("第" + i + "个元素不存在");// 输出异常
}
return p.getData();// 返回元素p
}
//在带头结点的循环单链表中第i个数据元素之前插入一个值为x的数据元素
public void insert(int i, Object x) throws Exception {
Node p = head;// 初始化p为头结点,j为计数器
int j = -1; // 第i个结点前驱的位置
while ((p!=head || j == -1) && j < i - 1) {// 寻找i个结点的前驱
p = p.getNext();
j++;// 计数器的值增1
}
if (j > i - 1 || (p==head && j != -1)) // i不合法
throw new Exception("插入位置不合理");// 输出异常
Node s = new Node(x); // 生成新结点
s.setNext(p.getNext());// 插入单链表中
p.setNext(s);
}
// 将循环单链表中第i个数据元素删除。其中i取值范围为:0≤i≤length()- 1,如果i值不在此范围则抛出异常
public void remove(int i) throws Exception {
Node p = head.getNext();// p指向要删除结点的前驱结点
int j = -1;
while((p!=head || j == -1) && j < i - 1) {// 寻找i个结点的前驱
p=p.getNext();
++j;// 计数器的值增1
}
if(j > i - 1 || p==head) { // i小于0或者大于表长减1
throw new Exception("删除位置不合理");// 输出异常
}
p.setNext(p.getNext().getNext());// 删除结点
}
// 在带头结点的循环单链表中查找值为x的元素,如果找到,则函数返回该元素在线性表中的位置,否则返回-1
public int indexOf(Object x) {
Node p = head.getNext();// 初始化,p指向首结点,j为计数器
int j = 0;
while (p!=head && !p.getData().equals(x)) {// 从单链表中的首结点元素开始查找,直到p.getData()指向元素x或到达单链表的表尾
p = p.getNext();// 指向下一个元素
j++;// 计数器的值增1
}
if (!p.equals(head))// 如果p指向表中的某一元素
return j;// 返回x元素在顺序表中的位置
else
return -1;// x元素不在顺序表中
}
// 输出循环链表中的数据元素
public void display() {
Node node = head.getNext();// 取出带头结点的单链表中的首结点元素
while (!node.equals(head)) {
System.out.print(node.getData() + " ");// 输出数据元素的值
node = node.getNext();// 取下一个结点
}
System.out.println();// 换行
}
}
1.基础结构对象DuLNode
public class DuLNode {
private Object data;// 存放结点值
private DuLNode prior; // 前驱结点的引用
private DuLNode next; // 后继结点的引用
public DuLNode() {// 无参数时的构造函数
this(null);
}
public DuLNode(Object data) {// 构造值为data的结点
this.data = http://www.mamicode.com/data;
this.prior = null;
this.next = null;
}
public Object getData() {
return data;
}
public DuLNode getNext() {
return next;
}
public DuLNode getPrior() {
return prior;
}
public void setData(Object data) {
this.data = http://www.mamicode.com/data;
}
public void setNext(DuLNode next) {
this.next = next;
}
public void setPrior(DuLNode prior) {
this.prior = prior;
}
}
2.双向链表操作接口类
public interface IList {
public void clear(); // 将一个已经存在的线性表置成空表
public boolean isEmpty(); // 判断当前线性表中的数据元素个数是否为0,若为0则函数返回true,否则返回false
public int length(); // 求线性表中的数据元素个数并由函数返回其值
public Object get(int i) throws Exception;// 读取到线性表中的第i个数据元素并由函数返回其值。其中i取值范围为:0≤i≤length()-1,如果i值不在此范围则抛出异常
public void insert(int i, Object x) throws Exception;// 在线性表的第i个数据元素之前插入一个值为x的数据元素。其中i取值范围为:0≤i≤length()。如果i值不在此范围则抛出异常,当i=0时表示在表头插入一个数据元素x,当i=length()时表示在表尾插入一个数据元素x
public void remove(int i) throws Exception;// 将线性表中第i个数据元素删除。其中i取值范围为:0≤i≤length()- 1,如果i值不在此范围则抛出异常
public int indexOf(Object x);// 返回线性表中首次出现指定元素的索引,如果列表不包含此元素,则返回 -1
public void display();// 输出线性表中的数据元素
}
3. 双向循环链表及其基本操作
public class DuLinkList implements IList{
private DuLNode head;// 双向循环链表的头结点
// 双向链表的构造函数
public DuLinkList() {
head = new DuLNode(); //初始化头结点
head.setPrior(head);//初始化头结点的前驱和后继
head.setNext(head);
}
//n为该双向链表的元素个数
public DuLinkList(int n) throws Exception {
this();
Scanner sc=new Scanner(System.in);// 构造用于输入的对象
for (int j = 0; j < n; j++)
insert(j,sc.next());//生成新结点,插入到表头
}
// 在双向循环链表的第i个数据元素之前插入一个值为x的数据元素,i等于表长时,p指向头结点;i大于表长时,p=NULL。
// 其中i取值范围为:0≤i≤length()。当i=0时表示在表头插入一个数据元素x,当i=length()时表示在表尾插入一个数据元素x
public void insert(int i, Object x) throws Exception {
DuLNode p = head.getNext();// 初始化,p指向首结点,j为计数器
int j = 0;
while (p!=null && j < i) {// 寻找插入位置i
p = p.getNext();// 指向后继结点
j++;// 计数器的值增1
}
if (j>i && p==null)// i小于0或者大于表长
{
throw new Exception("插入位置不合理");
}
//生成新结点
DuLNode s = new DuLNode(x);
//i位置之前
s.setNext(p);
s.setPrior(p.getPrior());
p.getPrior().setNext(s);
p.setPrior(s);
}
// 将双向循环链表中第i个数据元素删除。其中i 取值范围为:0≤i≤ength()-1
public void remove(int i) throws Exception {
DuLNode p = head.getNext();// 初始化,p指向首节点结点,j为计数器
int j = 0;
while (p!=head && j < i) {// 寻找删除位置i
p = p.getNext();// 指向后继结点
j++;// 计数器的值增1
}
if (j>i) // i小于0或者大于表长减1
throw new Exception("删除位置不合理");// 输出异常
p.getPrior().setNext(p.getNext());
p.getNext().setPrior(p.getPrior());
}
// 将一个已经存在的双向循环链表置成空表
public void clear() {
head.setPrior(head);
head.setNext(head);
}
// 判断当前双向循环链表是否为空
public boolean isEmpty() {
return head==head.getNext();
}
// 读取双向循环链表中的第i个数据元素
public Object get(int i) throws Exception {
DuLNode p = head.getNext();// 初始化,p指向首结点,j为计数器
int j = 0;
while (p!=head && j < i) {// 从首结点向后查找,直到p指向第i个元素或p指向头结点
p = p.getNext();// 指向后继结点
++j;// 计数器的值增1
}
if (j > i || p==head) { // i小于0或者大于表长减1
throw new Exception("第" + i + "个元素不存在");// 输出异常
}
return p.getData();// 返回元素p
}
// 求双向循环链表中的数据元素个数并由函数返回其值
public int length() {
DuLNode p = head.getNext();// 初始化,p指向首结点,length为计数器
int length = 0;
while (p!=head) {// 从首结点向后查找,直到p指向头结点
p = p.getNext();// 指向后继结点
length++;// 长度增1
}
return length;
}
// 在双向循环链表中查找值为x的元素,如果找到,则函数返回该元素在线性表中的位置,否则返回-1
public int indexOf(Object x) {
DuLNode p = head.getNext();// 初始化,p指向首结点,j为计数器
int j = 0;
while (p!=head && !p.getData().equals(x)) {// 从链表中的首结点元素开始查找,直到p.getData()指向元素x或到达链表的表尾
p = p.getNext();// 指向下一个元素
j++;// 计数器的值增1
}
if (p!=head)// 如果p指向表中的某一元素
return j;// 返回x元素在顺序表中的位置
else
return -1;// x元素不在顺序表中
}
//双向链表输出
public void reverse()
{
DuLNode p=head.getNext();
head.setNext(null);
DuLNode q=null;
while(p!=head)
{
//保存下一个值
q=p.getNext();
p.setNext(head.getNext());
p.setPrior(head);
head.setNext(p);
p=q;
}
}
public void display() {
DuLNode node = head.getNext();// 取出带头结点的双向链表中的首结点
while (node!=head && node!=null) {
System.out.print(node.getData() + " ");// 输出数据元素的值
node = node.getNext();
}
System.out.println();
}
public DuLNode getHead() {
return head;
}
public void setHead(DuLNode head) {
this.head = head;
}
}
小结:假如是循环链表呢?大家不妨自己写写,我这里提供一个带头的循环链表的代码如下:
public class CircleLinkList implements IList{
//头节点
public Node head;
// 自连接的循环链表
public CircleLinkList() {
head = new Node();
head.setNext(head);
}
public Node getHead() {
return head;
}
public void setHead(Node head) {
this.head = head;
}
public CircleLinkList(int n,boolean order)
{
this();//初始化
if(order)
{
create1(n);//用尾插入法插入链表
}
else
{
create2(n);//用头插法逆位序建立单链表
}
}
//用尾插入法插入链表
public void create1(int n)
{
//输入数据
Scanner sc=new Scanner(System.in);
for(int i=0;i<n;i++)
{
try {
this.insert(this.length(),sc.next());
} catch (Exception e) {
e.printStackTrace();
}
}
}
//用头插法逆位序建立单链表
public void create2(int n)
{
//输入数据
Scanner sc=new Scanner(System.in);
for(int i=0;i<n;i++)
{
try {
this.insert(0,sc.next());// 生成新结点,插入到表头
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 将一个已经存在的带头结点的循环单链表置成空表
public void clear() {
head.setNext(head);//清空链表
}
// 判断当前带头结点的循环单链表是否为空
public boolean isEmpty() {
return head.getNext().equals(head);
}
// 求带头结点的循环单链表中的数据元素个数并由函数返回其值
public int length() {
//取得首节点
Node p=head.getNext();
int length=0;
while(p!=head)
{
p=p.getNext();
length++;
}
return length;
}
// 读取带头结点的循环单链表中的第i个数据元素
public Object get(int i) throws Exception {
Node p = head.getNext();// 初始化,p指向首结点,j为计数器
int j = 0;
while (p!=head && j < i) {// 从首结点向后查找,直到p指向第i个元素或p指向头结点
p = p.getNext();// 指向后继结点
++j;// 计数器的值增1
}
if (j > i || p==head) { // i小于0或者大于表长减1
throw new Exception("第" + i + "个元素不存在");// 输出异常
}
return p.getData();// 返回元素p
}
//在带头结点的循环单链表中第i个数据元素之前插入一个值为x的数据元素
public void insert(int i, Object x) throws Exception {
Node p = head;// 初始化p为头结点,j为计数器
int j = -1; // 第i个结点前驱的位置
while ((p!=head || j == -1) && j < i - 1) {// 寻找i个结点的前驱
p = p.getNext();
j++;// 计数器的值增1
}
if (j > i - 1 || (p==head && j != -1)) // i不合法
throw new Exception("插入位置不合理");// 输出异常
Node s = new Node(x); // 生成新结点
s.setNext(p.getNext());// 插入单链表中
p.setNext(s);
}
// 将循环单链表中第i个数据元素删除。其中i取值范围为:0≤i≤length()- 1,如果i值不在此范围则抛出异常
public void remove(int i) throws Exception {
Node p = head.getNext();// p指向要删除结点的前驱结点
int j = -1;
while((p!=head || j == -1) && j < i - 1) {// 寻找i个结点的前驱
p=p.getNext();
++j;// 计数器的值增1
}
if(j > i - 1 || p==head) { // i小于0或者大于表长减1
throw new Exception("删除位置不合理");// 输出异常
}
p.setNext(p.getNext().getNext());// 删除结点
}
// 在带头结点的循环单链表中查找值为x的元素,如果找到,则函数返回该元素在线性表中的位置,否则返回-1
public int indexOf(Object x) {
Node p = head.getNext();// 初始化,p指向首结点,j为计数器
int j = 0;
while (p!=head && !p.getData().equals(x)) {// 从单链表中的首结点元素开始查找,直到p.getData()指向元素x或到达单链表的表尾
p = p.getNext();// 指向下一个元素
j++;// 计数器的值增1
}
if (!p.equals(head))// 如果p指向表中的某一元素
return j;// 返回x元素在顺序表中的位置
else
return -1;// x元素不在顺序表中
}
// 输出循环链表中的数据元素
public void display() {
Node node = head.getNext();// 取出带头结点的单链表中的首结点元素
while (!node.equals(head)) {
System.out.print(node.getData() + " ");// 输出数据元素的值
node = node.getNext();// 取下一个结点
}
System.out.println();// 换行
}
}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。