Java数据结构学习之 有序非循环双向链表的实现

来源:互联网 发布:身份证模拟软件 编辑:程序博客网 时间:2024/05/18 07:18

package PersonToFile;

/**
 * 带头结点的非循环有序双向链表的节点 类型参数E必须实现Comparable<E>接口
 *
 * @author QQ1392315666 。
 * @version 3.0 2012年11月3日
 */
// TODO: 类型参数为什么可以继承接口?
public class Node<E extends Comparable<E>> implements Comparable<E> {
 E data;
 Node<E> next;
 Node<E> previous;

 public Node(E data) {
  this.data = data;
  this.previous = null;
  this.next = null;
 }

 // TODO:当E为String时,不会调用这个方法,为什么?
 @Override
 public int compareTo(E other) {
  return this.data.compareTo(other);
 }

 // TODO:如果data的类型是String,不会调用这个方法,为什么?
 public String toString() {
  return this.data.toString();
 }

}

package PersonToFile;

import java.io.File;
import java.io.PrintWriter;

/**
 * 带头结点的非循环有序双向链表
 *
 * @author QQ1392315666
 * @version 3.0 2012年11月3日
 */
public class DoubleSortedLinkedList<E extends Comparable<E>> {
 public Node<E> header; // 头节点
 public int size;// 节点数目

 /**
  * 将链表写入文件 。 2012年11月4日1:32:22
  *
  * @param String
  *            文件路径
  * @return Boolean 成功返回true,失败返回false
  * */
 public Boolean writeToFile(String fileName) throws Exception {
  Boolean r = true;
  try {
   File file = new File(fileName);
   if (file.exists())
    file.delete();
   if (file.createNewFile() && file.canWrite()) {
    PrintWriter out = new PrintWriter(file);
    out.print(this.toString());
    out.close();
   }
  } catch (Exception e) {
   r = false;
   throw new Exception("writeToExcel异常:" + e.getMessage());
  }
  return r;
 }

 /**
  * 插入新节点,需保证插入后有序(升序)
  * */
 // TODO:需要优化
 public Node<E> append(Node<E> e) {
  Node<E> front, current;// front用于指向current的前驱,current指向当前节点'
  int r;// r用于保存data的比较结果
  front = header;
  current = header.next;
  if (current == null)// 原链表为空
  {
   header.next = e;
   e.previous = header;
  }
  while (current != null) {
   r = current.data.compareTo(e.data);
   if (r < 0) {
    front = current;
    current = current.next;
   }
   // 当前节点大于e,则e作为current的前驱
   if ((r == 0) || (r > 0)) {
    front.next = e;
    e.previous = front;
    e.next = current;
    current.previous = e;
    size++;// 线性表长度增加
    return e;
   }
  }// end while
   // 最后一个节点仍小于e
  front.next = e;
  e.previous = front;
  size++;
  return e;// 返回新增节点
 }

 /**
  * @param Node
  *            <E> 待查找节点
  * @return 带查找节点的引用
  * */
 public Node<E> find(Node<E> e) {
  Node<E> p;
  p = header.next;
  while (p != null) {
   if (p.data.compareTo(e.data) == 0)
    return p;
   else
    p = p.next;
  }
  return null;
 }

 public E remove(Node<E> e) throws Exception {
  if (e == header)
   throw new Exception("不能删除头结点。");

  E result = e.data;
  e.previous.next = e.next;
  if (e.next != null)
   e.next.previous = e.previous;
  e.next = e.previous = null;
  size--;
  return result;
 }

 /**
  * 删除链表中全部的指定节点
  *
  * @param Node
  *            <E> 待删除节点
  * */
 public void removeAll(Node<E> e) throws Exception {
  Node<E> p;
  do {
   p = this.find(e);
   if (p != null) {
    this.remove(p);
   } else {
    break;// 提高效率;无需继续搜寻
   }
  } while (p != null);
 }

 public String toString() {
  String str = "";
  Node<E> p;
  p = header.next;

  if (p != null) {
   // 如果data的类型是String,加双引号
   if (p.data instanceof java.lang.String)
    str += "\"" + p.data + "\"";
   else
    str += p.data;
   p = p.next;
  }
  while (p != null) {
   if (p.data instanceof java.lang.String)
    str += ",\"" + p.data + "\"";
   else
    str += p.data;
   p = p.next;
  }
  return str;
 }
}

package PersonToFile;

/**
 * 节点的data
 *
 * @author QQ1392315666
 * @version 1.0 2012年11月3日
 * */
public class Person implements Comparable<Person> {
 public String id;// 身份证号
 public String name;// 姓名
 public short age;// 年龄

 /**
  * @param id
  * @param name
  * @param age
  */
 public Person(String id, String name, short age) {
  this.id = id;
  this.name = name;
  this.age = age;
 }

 public Person() {
  this("-1", null, (short) -1);
 }

 @Override
 public int compareTo(Person other) {
  if (this.id.compareTo(other.id) > 0)
   return 1;
  else if (this.id.compareTo(other.id) < 0)
   return -1;
  else
   return 0;
 }

 /**
  * @param none
  * @return String 以逗号分隔num,name和age,以便导入到Excel中
  *
  * */
 @Override
 public String toString() {
  return this.id + "," + this.name + "," + this.age + "\n";
 }
}

package PersonToFile;

/**
 * 测试程序
 * @author QQ1392315666
 * @version 3.0 2012年11月4日0:57:33
 * */
import java.util.Random;
import java.util.Scanner;

public class Test_DoubleSortedLinkedList {
 public static void main(String[] args) {
  try {
   DoubleSortedLinkedList<Person> StudentDL = new DoubleSortedLinkedList<Person>();
   StudentDL.header = new Node<Person>(new Person());
   Node<Person> toAddNode = null, toDelNode = null;
   long id = -11;
   Random random = new Random(0);

   for (int i = 1; i < 11; i++) {
    id = Math.abs(random.nextLong());
    toAddNode = new Node<Person>(new Person("12345678901234567"
      + (id % 10), "赵钱孙李" + i % 3, (short) (id % 100)));
    StudentDL.append(toAddNode);
   }
   System.out.println("非循环有序双向链表:\n" + StudentDL);
   System.out.println("共有" + StudentDL.size + "个数据节点。");
   StudentDL.writeToFile("人员信息.txt");
   Scanner scan = new Scanner(System.in);
   System.out.println("输入待删除的节点的data:");
   // Boolean wrong = true;
   // TODO 如何在发生输入异常时,循环输入?
   String pid = scan.nextLine();
   toDelNode = new Node<Person>(new Person(pid, "某某人", (short) 11));
   StudentDL.removeAll(toDelNode);
   System.out.println("删除节点后:");
   System.out.println(StudentDL);
   System.out.println("共有" + StudentDL.size + "个数据节点。");
   StudentDL.writeToFile("人员信息.txt");
  } catch (Exception e) {
   System.out.println("发生异常" + e.getMessage());
  }
 }
}

 

原创粉丝点击