双向链表模拟

我们熟悉了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 = 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 = 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();// 换行

}

}

双向链表模拟

时间: 2024-10-09 22:58:01

双向链表模拟的相关文章

ACM/ICPC 之 用双向链表 or 模拟栈 解“栈混洗”问题-火车调度(Tshing Hua OJ - Train)

本篇用双向链表和模拟栈混洗过程两种解答方式具体解答“栈混洗”的应用问题 有关栈混洗的定义和解释在此篇:手记-栈与队列相关 列车调度(Train) Description Figure 1 shows the structure of a station for train dispatching. Figure 1 In this station, A is the entrance for each train and B is the exit. S is the transfer end.

hdu 6375 度度熊学队列 (链表模拟)

度度熊正在学习双端队列,他对其翻转和合并产生了很大的兴趣. 初始时有 N 个空的双端队列(编号为 1 到 N ),你要支持度度熊的 Q 次操作. ①1 u w val 在编号为 u 的队列里加入一个权值为 val 的元素.(w=0 表示加在最前面,w=1 表示加在最后面). ②2 u w 询问编号为 u 的队列里的某个元素并删除它.( w=0 表示询问并操作最前面的元素,w=1 表示最后面) ③3 u v w 把编号为 v 的队列“接在”编号为 u 的队列的最后面.w=0 表示顺序接(队列 v 

uva133-救济金发放

此题为小白书里数据结构基础关于线性表的题目 翻译请戳 http://luckycat.kshs.kh.edu.tw/ 解题思路 当时直接用动态的双向链表模拟了... 但是用双向链表很纠结啊,如果你加入头结点之后的查找会变得很麻烦, 如果不加头结点的话,插入节点会很麻烦... 但已经写了就不想改了...如果你用静态链表实现亦可以,看个人喜好. 注意 如果有头结点,一开始从头结点数起,第一次删除后,以后的删除都要忽略头结点(跳过不计). 代码: #include<iostream> #includ

Tsinghua OJ Zuma

Description Let's play the game Zuma! There are a sequence of beads on a track at the right beginning. All the beads are colored but no three adjacent ones are allowed to be with a same color. You can then insert beads one by one into the sequence. O

My to do 12.25

Merry Christmas 新的一年要来了,参加工作转眼也快半年了.回顾以往,多逢贵人.不忘初心,感慨良多.祝所有的朋友都能幸福,愿望都可以实现,日子越过越好~ Look Back 作为GH加入北京移动总部的这个项目,遇到不少大神,学东西也确实比学生时代快的多.最钦佩的还是同是GBS的老陈.陈叔细心又不厌其烦,漫不经心地分享很多人生哲理,让人由衷产生“虽不能至,心向往之”的仰慕之意.这就是所谓的人格魅力吧,不是说技术多牛逼,而是技术.地位那么高的情况下,为人还这么谦和. 一代宗师里说:叶里藏

POJ3750_小孩报数问题【约瑟夫环】【string】【list】

小孩报数问题 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10309 Accepted: 4783 Description 有N个小孩围成一圈,给他们从1开始依次编号,现指定从第W个开始报数,报到第S个时,该小孩出列,然后从下一个小孩开始报数,仍是报到S个出列,如此重复下去,直到所有的小孩都出列(总人数不足S个时将循环报数),求小孩出列的顺序. Input 第一行输入小孩的人数N(N<=64) 接下来每行输入一个小孩的名字

【暑假】基本的数据结构知识点总结梳理

基本的数据结构知识点总结梳理 数据结构: 栈.队列(deque).链表.树和二叉树.图 算法: 1.  树的遍历pre_order  in_order  post_order :递归完成 2.  根据in_order与另一种遍历构树:pre_order|post_order寻找根节点,in_order判断左右子树,递归处理. 3.  根据BFS与DFS构树:由BFS序列中的位置判断结点关系,顺DFS序列依次为每个结点建立关系.应用栈记录父结点. 4.  DFS求连通块 5.  BFS求最短路:适

CodeForces 670E Correct Bracket Sequence Editor

链表,模拟. 写一个双向链表模拟一下过程. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include&

CodeForces 670E(模拟双向链表)

题意:给你一串合法的括号和当前光标的位置和一些操作,问操作完之后的串是怎么样的 思路:模拟一个双向链表的操作,首先先预处理出配对的括号组,然后模拟即可 #include<bits\stdc++.h> using namespace std; const int maxn = 1e6; struct Node { int l,r; }nodes[maxn]; char s1[maxn],s2[maxn]; int a[maxn],d[maxn]; int main() { int n,m,pos