遍历自定义链接列表

时间:2011-06-28 05:04:53

标签: java traversal singly-linked-list

我正在编写一个程序来模拟内存碎片。输入文件说明在什么时间需要输入哪些段。

示例文件是:

N  
C 200  
P 1 2 3  
P 2 3 4  
P 2 3 1  
R  
E

其中C是内存大小,P是订单中的细分(大小,开始时间和生命周期),R(应该)打印出一份报告什么片段,任何洞都在记忆中以及在哪里。

此分配的一个规则是创建事件的链接列表,其中段的插入和删除被创建为事件,我需要遍历事件列表。 更新:我有不同的东西,但我知道它确实没有将我的事件插入事件列表。我不明白为什么。有谁看到我的逻辑在哪里?

import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;

public class TestEventList{
    public static void main(String[] args){
    //read file
    File file = new File("b.txt");

    try {
        Scanner scanner = new Scanner(file);
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();

            //send it to interpret file method:
            interpretFile(line);
        }
    } catch (FileNotFoundException ex) {
        ex.printStackTrace();
    }  //end try-catch
}

public static void interpretFile(String command) {
    EventList evtList = new EventList();

    Scanner sc = new Scanner(command);


    char initialCommand = command.charAt(0);

    if (initialCommand == 'N') {
        System.out.println("Name");
    } else {
    }//end else
    //file error

    char commandCode = command.charAt(0);
    String skip = sc.next();  //skips next character to get to integers
    switch (commandCode) {
    case 'C':/*create Memory! which means, create Event!
                Form: Event(int startTime, Segment memSegment)*/
        int size = sc.nextInt();

        Segment defaultMemoryNode = new Segment(size, 100, false );
        /*create event node*/
        Event insertDefaultNode = new Event(0, defaultMemoryNode);
        /*insert this event*/
        evtList.insertEvent(insertDefaultNode);

        break;

    case 'P':

            int segmentSize = sc.nextInt();
            int segmentStart = sc.nextInt();
            int segmentLife = sc.nextInt();

            int segmentExpiration = segmentLife + segmentStart;

            Segment memorySegment = new Segment(segmentSize, segmentExpiration, true );
            Event addSegment = new Event(segmentStart, memorySegment);
            evtList.insertEvent(addSegment);

            memorySegment.occupied = false;

            Event removeSegment = new Event(segmentExpiration, memorySegment);
            evtList.insertEvent(removeSegment);

            break;

    case 'R':
        evtList.traverseEventList();

        break;
    case 'E':
        System.exit(0);
        }//end switch

}//end interpretfile method
}  //end class T.E.L.

/*This class has-a Linked List, has-a memoryNode, has-a Segment*/
class MemoryList{

 private Node memoryNode = new Node();
 private Segment memorySegment = new Segment();
 private LinkedList memoryList = new LinkedList();
 Node head;
 Node current;

public MemoryList(){
   super();
}
   /*define blocks and holes*/
   public void insertBlock(Segment memorySegment) {
    current = head;
    if (current == null) {
        memoryList.Add(memorySegment);
        System.out.println(memorySegment.size);
        }
    else {
        System.out.println("Checking for room");
        System.out.println(current.getSize());
        int invalidFit=0;
        if(current.getStatus() == false && current.getSize()>=memorySegment.size){
            System.out.println("Verified space");
            int freeSpace = current.getSize() - memorySegment.size;
            memoryList.Add(memorySegment);
            createHole(freeSpace);
            current = current.next;
         }  //end if
         else {
            current = current.next;

        } //end else
    }//end else
  }  //end insert block

  public void removeBlock(Segment expiredSegment){
    current = head;
    //search for segment

    while(current.next != null){
        if(current.getTimetoLeave() == expiredSegment.timeToLeave
                && current.getSize() == expiredSegment.size){

        memoryList.Remove(expiredSegment);
        int freespace = expiredSegment.size;
        createHole(freespace);
    }
        else{
            current = current.next;
        }
    }//end while
}

    private void createHole(int space) {
    Node hole = new Node(space, 100, false);
    memoryList.Add(hole);
    //test if there are two holes together. if so, mergeHoles.
    }

   *Merge 2 Consecutive Holes*/
   private void mergeHoles(Node a, Node b) {
   //getPrev(a);  //find previous of node a
   //use the size through the end of a's prev to
   //get start of prev.next (a)+

   //make a point to b.next?
  } //end mergeHoles

  public void traverseMemoryList(){
    current = head;

    if(current == null){
        System.out.println("Memoryless");
    }
    else{
        while(current.next != null){
            if(memoryNode.getStatus() == false){
                System.out.println("Hole");
                current = current.next;
            }
        }
        System.out.println("Segment of size " + current.getSize());
        current = current.next;
    }
   }

} //end MemoryList

class MemoryNode extends Node{
   public MemoryNode(){
    super();
   }


}
class Segment{
  int size;
  int timeToLeave;
  boolean occupied;

  /*constructor*/
  public Segment(){

  }

public Segment(int newSize, int newTime, boolean isOccupied){
    this.size = newSize;
    this.timeToLeave = newTime;
    this.occupied = isOccupied;
 }

}

class Node {
     private int size;
     private int timeToDepart;
     boolean occupied;  // True if segment, false if hole
     Node next;
     public Object data;  //data in a node

    public Node() {
    }

    public Node(int segmentSize, int timeToLeave, boolean type) {
    this.size = segmentSize;
    this.timeToDepart = timeToLeave;
    this.occupied = type;

    }

    public int getSize() {
    return size;
    }

    public void setSize(int segmentSize) {
        size = segmentSize;
    }

    public int getTimetoLeave() {
        return timeToDepart;
    }

     public void setTimetoLeave(int timeToLeave) {
            timeToDepart = timeToLeave;
    }

    public void setStatus(boolean type) {
        occupied = type;
    }

    public boolean getStatus() {
        return occupied;
    }

}  //end Node

/* class LL has-a Node*/
class LinkedList{
  private Node listNode= new Node();

   Node current;
   Node head;
   Node prev;

   int size;

/*Constructors:*/
public LinkedList() {
    super();
}

public LinkedList(int j, int k, boolean l) {
    super();  //essentially the same as a node
}

/*LL proprietary methods*/
 /*test if the list is empty, to avoid NullPointerException*/
public boolean isEmpty() {
    return head == null;
}
//insert method:

public void Add(Object data1) {
    listNode.data = data1;

    /*special case: list is empty*/
    if (isEmpty()) {
        listNode.next = head;
        head = listNode;
        head.data = listNode.data;
    }

    else{
        current = head;

        while(current.next != null)
    {
        current.data = data1;
        current.next = null;
        head = current;
    }
        current.data = data1;
        current.next = head; //newNode now points to head
        head = current;      //now newNode is the head
    }
}

public void Remove(Object delData) {
    /*pointers*/

    //special case: if head is the removed node;
    if (current.data == delData) {
        head = current.next;
    } else {
        prev = head;  //it's not the head, keep moving.
        current = current.next;

        while (current.next != null) {  //reached end of list
            if (current.data == delData) {      //if
                prev.next = current.next;       //just skip the current node
            } else {
                prev = current;          //now prev is that node
                current = current.next;  //current is the next node

            }
        }  //end while
        //what if current.next = null (it's at the end)?
        if (current.next == null && current.data == delData) {
            prev.next = null;

        }
    }//end else
}
public void traverse(){
    if(head== null){
        System.out.println("no elements to show");
    }
else{
    current = head;
    while(current.next != null){
        current = current.next;
    }

  }}
  }// end LL class

 /*class EventList has-an Event, is-a LinkedList*/
class EventList{
   private Event event = new Event();
   private LinkedList evtList = new LinkedList();
   private MemoryList memList = new MemoryList();
   Node current;
   Node head;
   int time;  //set to the most recent time

   /*constructor*/
   public EventList(){
    super();

  }

  public void actionOfEvent(Event event1){
    Segment p = event.getMemorySegment();
    if(p.occupied == true){
        insertSegment(event1);
    }
    else
        removeSegment(event1);
   }

  //a linked list to control creation of events
  public void insertEvent(Event event) {
    current = head;
    if(current == null){

        evtList.Add(event);
        System.out.println("Added 1st event " + event.startTime);
    }
    else{
        while(current.next != null){
            if(event.startTime <= event.getTime()){
                //if the event start was before the current time...
                evtList.Add(event);
                current = current.next;
            }
            else{
                current = current.next;
            }

        }//end while
        evtList.Add(event);
        System.out.println("Added 2nd event");
    }
   }//end insertEvent

  public void traverseEventList(){
    current = head;

    if(current == null){
        System.out.println("At time " + event.getTime());
        System.out.println("uneventful");
       }
    else{
        while (current.next != null){
        Segment segment1 = event.getMemorySegment();
        if(segment1.occupied = true){
            memList.insertBlock(segment1);
            System.out.println(segment1.size + " inserted");
        }

        else{
            memList.removeBlock(segment1);
            System.out.println(segment1.size + " removed from memory.");
        }


        }
      }
   }

  public void insertSegment(Event addEvent){
    addEvent.getMemorySegment();
    memList.insertBlock(addEvent.getMemorySegment());
    }
  public void removeSegment(Event expEvent){

}

} //end eventList

 /*class Event is-a Node*/
class Event{

   int startTime;
   Segment memoryNode;
   int time;

   public Event(){
       super();
   }

   //pretty much the same as Node.
   public Event(int newStartTime, Segment newMemNode){
      super();
      this.startTime = newStartTime;
      this.memoryNode = newMemNode;
   }

   public void setTime(int newStartTime){
      time = newStartTime;
   }

   public int getTime(){
    return time;
   }

   public void setMemorySegment(Segment newMemNode){
       memoryNode = newMemNode;
   }

   public Segment getMemorySegment(){
       return memoryNode;
   }

}//end class Event

class Report{
   int currentTime= 0;


    //this creates and prints the segments/holes in the list at curTime

}    

2 个答案:

答案 0 :(得分:1)

我运行了你的代码,似乎你从不打电话:

setMemoryNode();

这导致NullPointerExceptions。

此外:

一些多个事件实例是由这些行引起的:

EventSequenceList expiredNode = new EventSequenceList(newMemNode,
1, expir, 1, true);
insertEvent(expiredNode);

我会在我看到更多时编辑它。

答案 1 :(得分:1)

只是一些(其他)言论

<强>设计

你使用了很多继承。这真的有必要吗?稍后,对于生产代码,您应该考虑使用组合而不是继承和代码来对接口。这将消除许多丑陋的依赖关系并提高可维护性。现在你有了

  

EventSequenceList is-a MemoryList is-a LinkedList is-a 节点

仅仅从名称中我怀疑,LinkedList确实是一个节点。我希望在树或图中有一个 Node ,即使它通常是 has-a 关系。

<强>命名

有时您会破坏Java命名约定:方法名称不应以大写字母开头(如Add)。有时您使用单字母变量名称(就像在大多数构造函数中一样)。

有时,一个方法名称没有告诉我们,该方法实际上在做什么(比如iterpretFile实际上不解释文件但只有一个命令可能已从文件)


我看到的任务越多,我就越能感受到,你迟早会被设计困扰(比之后更早)。根据我的阅读,需要:

  • 一个事件模型类。一个Class,表示插入或删除事件。
  • 一个内存模型类。一个代表整个内存的类
  • 一个细分模型类。表示段的类。内存类具有列表或段数组
  • 一个包含所有事件的链接列表。此自定义链接列表可能能够在正确的位置插入事件
  • 一个报告类。可以创建和打印报告的类。
  • 一个输入文件解析器。它将使用输入
    • 创建一个内存类(具有适当数量的段)
    • P
    • 创建插入和删除事件
    • 在链接列表中插入事件

绝对没有继承。


编辑 - 回应您的上次评论

内存有一个单元格数组。单元格被索引,从0开始。它们没有链接,所以我实际上没有看到任何理由在这里使用LinkedList。内存模型可能如下所示:

public class Memory {
  private int[] cells;
  public Memory(int size) { cells = new int[size]; }
  public void store(int index, int value) { 
    if (index < 0 || index >= size) throw new IllegalArgumentException("..");
    cells[index] = value;
  }
  public int read(int index) {
    if (index < 0 || index >= size) throw new IllegalArgumentException("..");
    return cells[index];
  }
}

可以看作是Memory的子类。在现实生活中,如果可能,从内存管理器请求段并且管理器分配区域。段是完全独立的,它们之间没有链接,这里没有用于LinkedList。快速草稿:

public class MemoryManager {
  private Memory managedMemory;
  public MemoryManager(Memory memory) { this.memory = memory; }
  public Segment getSegment(int size) {
    int startAddress = allocateSegment(int size);
    if (startAddress != -1) {
      return new Segment(this, startAddress, size);
    }
    return null;
  }
}

public class Segment extends Memory {
  private MemoryManager memoryManager;
  private int startAddress;  // usually - a handle, so that the memoryManager can
                             // relocate the segment - we keep it simple
  public Segment(MemoryManager memoryManager, int startAdress, int size) {
    super(size);
    this.memoryManager = memoryManager;
    this.startAddress = startAddress;
  }

现在回到活动。

此任务的一个规则是创建事件的链接列表 [eventList = new EventList<Event>()] ,其中段的插入和删除被创建为事件 [new Event(EventType.INSERT, int time, Segment segment)); new Event(EventType.DELETE, int time, Segment segment);] ,我需要遍历事件列表 [for(Event event:eventList)]。

这就是任务。实现Event类,实现EventList类,实现一个小的枚举EventType。面临的挑战是在insert中实施EventClass方法,在正确的位置(时间戳)为一条P行插入两个事件。