- 浏览: 20639 次
- 性别:
- 来自: 长沙
最新评论
学过数据结构的应该对双向链表比较熟悉,但如果用java语言是怎么来实现的呢?本节是来讨论如何用java语言来实现链表,主要谈谈对双向链表的理解。
链表其实是一种非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接来实现的。链表由一系列的结点组成,结点是由存储数据元素的数据域和存储结点地址的指针域。对于单链表而言,结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。但当我们对单链表进行操作时,有时你要对某个结点前面的一个结点进行操作时,又必须从表头重新查找(这是由单链表的结构所造成的),这样接相当麻烦,为了解决这个问题,从而提出了双向链表。双向链表,结点包含一个存储数据元素的数据域,还有两个指针域,一个存储子结点地址,另一个存储父结点地址。
为了说明这些问题,我们先自定义一个双向链表:
package cn.链表;
/**
* 双向链表
* @author yl
*
*/
public class LinkNode {
private Object obj;
private LinkNode child;
private LinkNode parent;
public LinkNode(Object obj){
this.obj=obj;
}
//定义方法
public Object getObj(){
return obj;
}
public void setObj(Object obj){
this.obj=obj;
}
public LinkNode getChild(){
return child;
}
public void setChild(LinkNode child){
this.child=child;
}
public LinkNode getParent(){
return parent;
}
public void setParent(LinkNode parent){
this.parent=parent;
}
}
再来对这个链表进行测试:
package cn.链表;
/**
* 双向链表的测试
* @author Administrator
*
*/
public class LinkListTest {
private static LinkNode front=null;
private LinkNode last=front;
public static void main(String args[]){
LinkListTest list=new LinkListTest();
list.add("头结点");
for(int i=0;i<10;i++){
list.add("结点"+i);
}
//测试指定位置下取得结点
Object obj=list.getLinkNode(3).getObj();
//测试在指定位置插入元素
list.add(3, "新来的元素");
System.out.println("<><><><><><><>"+obj);
list.printLinkNode(front);
System.out.println("<><><><><><><><><><><><><><><><><><><><><");
// list.remove(3);
// list.printLinkNode(front);
list.upDate(3, "值被改变的元素");
list.printLinkNode(front);
System.out.println("<><><><><><><><><><><><><><><><><><><><><");
list.printLinkNode1(3);
}
/**
* 在链表的后面插入元素
* @param obj
*/
public void add(Object obj){
//根据给定的值创建结点
LinkNode node=new LinkNode(obj);
if(front==null){
//如果链表为空的时候
// front.setChild(node);
// node.setParent(front);
//第一个结点也即是最后一个结点
front=node;
last=front;
// System.out.println(front.getObj());
}
else{
//新插入的结点为最后一个结点
last.setChild(node);
node.setParent(last);
last=node;
}
}
/**
* 在指定位置插入元素
* @param index
* @param obj
*/
public void add(int index,Object obj){
//先创建结点
LinkNode node=new LinkNode(obj);
//判断传入的下标
if(index<0||index>size()){
throw new RuntimeException("下标越界:size:"+size()+"index:"+index);
}else{
//传入的下标符合要求
if(front==null){
//如果链表为空的时候
front=node;
last=front;
}else if(index==size()){
add(node);
}
else{
//链表不为空,取得当前下标的结点
LinkNode nownode=getLinkNode(index);
//得到父结点
LinkNode fnode=nownode.getParent();
//重新定义新的引用关系
fnode.setChild(node);
node.setParent(fnode);
node.setChild(nownode);
nownode.setParent(node);
}
}
}
/**
* 根据下标,删除当前的结点
* @param index
*/
public void remove(int index){
if(index<0||index>size()){
throw new RuntimeException("下标越界:size:"+size()+"index:"+index);
}else{
//传入的下标符合要求
if(front==null){
//如果链表为空的时候
System.out.println("链表为空,不能删除元素啦!!!");
}
else{
//链表不为空,取得当前下标的结点
LinkNode nownode=getLinkNode(index);
//得到父结点
LinkNode fnode=nownode.getParent();
//得到父结点
LinkNode cnode=nownode.getChild();
//重新定义新的引用关系
fnode.setChild(cnode);
cnode.setParent(fnode);
}
}
}
/**
* 根据下标取得当前的结点
* @param index 下标值
* @return
*/
public LinkNode getLinkNode(int index){
//判断传入的下标
if(index<0||index>size()){
throw new RuntimeException("下标越界:size:"+size()+"index:"+index);
}else{
//先取得头结点
LinkNode node=front;
int i=0;
while(i<index){
i++;
node=node.getChild();
}
return node;
}
}
/**
* 在指定的位置,更新该结点,结点的值为obj
* @param index
* @param obj 更改的结点的值
*/
public void upDate(int index,Object obj){
if(index<0||index>size()){
throw new RuntimeException("下标越界:size:"+size()+"index:"+index);
}else{
//传入的下标符合要求
if(front==null){
//如果链表为空的时候
System.out.println("链表为空,不能更新元素啦!!!");
}
else{
//链表不为空,取得当前下标的结点
LinkNode nownode=getLinkNode(index);
//给结点重新赋值
nownode.setObj(obj);
}
}
}
/**
* 得到链表的长度
* @return
*/
public int size(){
if(front==null){
//链表为空
return 0;
}else{
//不为空
LinkNode node=front;
int count=0;
while(node!=null){
count++;
node=node.getChild();
}
return count;
}
}
/**
* 打印链表
* @param node 传入链表的头结点
*/
public void printLinkNode(LinkNode node){
if(front==null){
System.out.println("此链表为空!!!");
}else{
//先取得头结点
LinkNode n=front;
//遍历链表
while(n!=null){
Object obj=n.getObj();
System.out.println(obj);
n=n.getChild();
}
}
}
/**
* 根据指定的位置来前后遍历
* @param index
*/
public void printLinkNode1(int index){
if(index<0||index>size()){
throw new RuntimeException("下标越界:size:"+size()+"index:"+index);
}
LinkNode nownode=getLinkNode(index);
LinkNode cnode=nownode.getChild();
int i=index;
//往前遍历
while(nownode!=null&&i>=0){
Object obj=nownode.getObj();
System.out.println(obj);
i--;
nownode=nownode.getParent();
}
nownode=getLinkNode(index);
//往后遍历
while(nownode!=null&&i<size()){
Object obj=nownode.getObj();
System.out.println(obj);
i++;
nownode=nownode.getChild();
}
}
}
下面也附了代码,自己可以拿去运行下。由于本人能力所限,如有什么问题,希望牛人指出。
<!--EndFragment-->
- LinkNode.rar (340 Bytes)
- 描述: 自定义的双向链表
- 下载次数: 8
- LinkListTest.rar (1.4 KB)
- 下载次数: 7
发表评论
-
深入理解HashMap(一)
2011-11-24 02:09 793以前学习HahsMap都是粗略的了解一下,能够用就行了。这次对 ... -
文件的压缩
2011-08-15 01:53 750本节主要是利用huffman树的原理来对文件进行处理,从而达到 ... -
数组转换成二叉树
2011-08-15 01:20 2689前面介绍了双向链表,其实二叉树也相当于一个链表。二叉树相对而言 ... -
多线程02
2011-08-03 00:17 671前面一节我们是通过继承Thread这个类来实现多线程,而如 ... -
多线程01
2011-08-02 00:08 581Java是支持多线程的语言,要想了解线程,我们得先知道进程。所 ... -
"= =" 和equals()的区别
2011-07-29 01:02 716在Java程序中,要比较两个对象是否相等,经常会使用到“= = ... -
"= =" 和equals()的区别
2011-07-29 01:00 0在Java程序中,要比较两个对象是否相等,经常会使用到“= = ... -
文件操作
2011-07-27 02:50 613一、File类 在整个io包中,唯一与文件本身有关的 ... -
异常的捕获与处理
2011-07-26 21:25 692在我们编写java程序时,我们经常遇到的问题就是:程序老出现问 ... -
递归算法
2011-07-26 00:27 759递归算法是一种特殊的调用形式,是方法自己调用自己,这样有点 ... -
小议Java关键字
2011-07-23 20:50 654在Java的学习过程中,我 ... -
Java中的数据结构
2011-07-05 22:20 781Java中的数据结构其实 ... -
类和对象总结
2011-05-12 19:40 608现在我们已经对java有一定的了解了,它是一个面向对象的 ... -
java入门知识小总结
2011-05-12 19:37 457谈到java,我们都知道其有一个面向对象的编程语言。在所有的编 ...
相关推荐
通过java实现的双向链表,及反转功能,可能对面试有用哦
JAVA实现链表_双向链表
用Java定义一个双向链表,实现链表的基本操作: 初始化、获取头结点、添加新元素、删除链表元素、 获取链表元素、查找链表元素、更新链表中某个元素、 判断链表是否为空、求链表元素个数、输出链表元素、清空链表。
操作包括: 1. 在头部添加结点 2. 在尾部添加结点 3. 遍历 4. 逆置 5. 删除
已知N个人(以编号1,2,3...n分别表示)围成一个圈。 从编号为K的人开始报数,数到M的那个人出列,他的下一个人又从1开始报数,依照此规律重复下去,直到圆圈中的人全部出列。 问题:请打印出这N个的...双向链表实现的
相信大家都明白 LinkedList 是基于双向链表而实现的,本篇文章主要讲解一下双向链表的实现,并且我们参考 LinkedList 自己实现一个单链表尝试一下。 什么是链表? 简单的来讲一下什么是链表:首先链表是一种线性的...
用java实现双向链表的完整操作,主要用到内部类实现。
* 基于双向链表实现双端队列结构 */ package dsa; public class Deque_DLNode implements Deque { protected DLNode header;//指向头节点(哨兵) protected DLNode trailer;//指向尾节点(哨兵) protected ...
基数排序(radix sort)又称桶排序(bucket sort),相对于常见的比较排序,基数排序是一种分配式排序,需要将关键字...为了尽可能少的消耗复制时占用的空间,桶的数据结构选择链表,为了构造队列,选择使用双向列表。
Java算法实例-双向链表操作,封装性高,考试、学习都可使用
使用java语言实现双向链表,提供测试用例说明功能
操作系统c++编程实现安全型双向链表,线程的创建,利用线程对链表进行增删改操作,并检验结果是否正确
主要介绍了Java实现双向链表(两个版本)的相关资料,需要的朋友可以参考下
约瑟夫问题,通过类实现的链表,并加以改进,做成双向链表
Java 有序 非循环 双向 链表 算法 实例
双端链表和双向链表Java代码
JAVA实现链表,双向链表.pdf
在双向链表上实现快速排序的递归算法 输入的形式:元素个数、元素都为整型。 输入值范围:元素个数为非负正整数,需要排序的元素都为整型。 输出的形式:排序前的元素序列和排序后的元素序列。 程序的功能:对用户...