2012-08-01 66 views
1

现在正在使用Java来处理此项目一段时间。建议我为我的程序使用链接列表或数组列表,这非常合理。然而,教授说我们必须制作和使用我们自己的链接列表利用节点。尽管在课堂上进行了一些研究和问询,但与Nodes合作让我感到非常困惑。我确信这是一件简单的事情,但我现在处于完全失落状态。这是列表存储的类(我认为)。它被称为飞机,因为我们正在创建一个列表来存储多架飞机和一些与它们相关的细节(飞行名称,速度,高度,飞机类型)。我有一个用户与之交互的主类(未列出) - 我已经很熟悉这个类。仅使用节点创建Java链接列表的帮助

package airTraffic; 

public class Aircraft { 

public static String name; 
public static String type; 
public static int speed; 
public static int alt; 

Aircraft nextCraft; 

public Aircraft (String n, String t, int s, int a) { 
    name = n; 
    type = t; 
    speed = s; 
    alt = a; 
} 

public Aircraft() { 

} 

public static void setName(String n) { 
    name = n; 
} 

public static String getName (String lookUp) { 
    return name; 
} 

public static void removeName() { 
    //remove the flight - not sure what to place here 
} 

public static void setType (String t) { 
    type = t; 
} 

public static String getType() { 
    return type; 
} 

public static void setSpeed (int s) { 
    speed = s; 
} 

public static int getSpeed() { 
    return speed; 
} 

public static void setAlt(int a) { 
    alt = a; 
} 

public static int getAlt() { 
    return alt; 
} 

public Aircraft next = null; 

//auto generated method from ATControl 
public static void add(String s) { 

} 

//auto generated methods from ATControl - what goes here??? 
public static void remove() { 

} 

public Object getNext() { 
    // TODO Auto-generated method stub 
    return null; 
} 

public void setNext(Object next2) { 
    // TODO Auto-generated method stub 

} 
} 

下面,我有我认为是创建和存储节点的类。这是我非常困惑,并认为我错了。我不知道如何调用节点来实际添加和存储数据。我还需要能够获得的节点(通过飞行名),并删除该节点(通过飞行名)

package airTraffic; 

import java.util.*; 
import airTraffic.Aircraft; 

public class ATControl { 


static Main m = new Main(); 
Aircraft aircraft = new Aircraft(); 

//declare node names for list 
public static Aircraft head = new Aircraft(); 
public static Aircraft tail = new Aircraft(); 

// stores data 
private static final int INITIAL_ALLOCATION = 20; 
private static int size = INITIAL_ALLOCATION; 

// tells list to add nodes 
public static void Nodes (String s, int n) { 
    n = size; 
    head.next = tail; 
    tail.next = tail; 
    Aircraft temp = head; 
    for (int i= 0; i < size; ++i) { 
     temp.next = new Aircraft(); 
     temp = temp.next; 
    } 
    temp.next = tail; 
} 

public static void addNodes (int n) { 
    n = size; 
    Aircraft temp = new Aircraft(); 
    Aircraft current = head; 
    for (int i = 1; i < n && current.getNext() != null; i++) { 
     current = (Aircraft) current.getNext(); 
     temp.setNext(current.getNext()); 
     current.setNext (temp); 
     size++; 
    } 
} 

//add plane and details 
public static void addToList (Scanner in) { 
    // should add new aircraft to new node on linked list 
    System.out.printf("Enter flight number: "); 
    String add = in.next(); 
    Aircraft.setName (add); 
    ATControl.addNodes (Integer.parseInt(add)); 

    //type of plane 
    System.out.printf("Enter type of plane: "); 
    String plane = in.next(); 
    Aircraft.setType (plane); 

    //plane speed 
    System.out.printf("Enter current speed: "); 
    int speed = in.nextInt(); 
    Aircraft.setSpeed (speed); 
    ATControl.addNodes (Integer.parseInt(add)); 


    //add Altitude 
    System.out.printf("Enter current altitude: "); 
    int alt = in.nextInt(); 
    Aircraft.setAlt(alt); 
    ATControl.addNodes (Integer.parseInt(add)); // I am fairly certain this is wrong 
} 

//show flight 
public static void showFlight (Scanner in) { 
    System.out.printf("Enter flight number for details: "); 
    String lookUp = in.next(); 
    Aircraft.getName(lookUp); 

} 
// display all flights 
public static void displayAll (Scanner in) { 
    System.out.printf("All flights: "); 

} 
//remove flight 
public static void removeFlight (Scanner in) { 
    System.out.printf("Enter flight number to be removed: "); 

} 
} 

回答

0

公共类节点{

public int item; 
    public Node next; 
    public Node tail; 


    Node() {     
     item = 0; 
     next = null; 
     tail = null ;  
    } 

    Add Node(node tail, node new) { 

     tail.next = new; 
     tail.tail = new 
     new.tail =null 

    } 

};

我希望我没有让事情变得更糟。祝你好运。

飞机类可以扩展节点类。看看java中的childfactory类。它会给你一个你将在节点类中使用的方法类型的例子。重新思考你的课程。也许删除Airplane将是节点类中的一种方法,如删除节点。任何在节点上工作的东西,比如插入或添加新的,删除和排序都可以添加到节点类中。然后,您可以在添加更多类时重用此类。

http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

1

我觉得你已经很接近 - 但它很难说究竟是怎么回事你ATControl类。通常,链表上的add方法需要一个节点(在你的情况下是飞机),而不是数字。

链接列表的关键是每个节点都有一个指向列表中下一个的指针。在你的飞机舱中,你有:飞机下一个,它将作为指针。

我建议在实施的ATControl以下方法:

public static Aircraft getUserInput(Scanner in) 
{ 
    Aircraft aircraft = new Aircraft(); 

    // get your values from the user and set them in your new aircraft 
    return aircraft; 
} 

public static void add(Aircraft aircraft) 
{ 
    // starting at head, walk through the list (repeatedly call next on 
    // the current Aircraft) until you reach the desired position 

    Aircraft temp = head; 

    while (temp != null) // ... 
} 

public static void remove(String flightNum) 
{ 
    // again, the same way you did in add, walk through the list until you find it 
    if (current.getName().equals(flightNum)) 
     // we found it, so remove it 
} 
2

你越来越接近。首先链表是一个对象列表,通常称为节点,每个节点都有一个或多个指向其他对象的链接。在你的情况下,节点是飞机。

这会帮助你一下:Wikipedia:Linked List

你的主要问题到目前为止是,你不必在你的飞机类的链接。由于这是一个链表,因此您需要在列表中包含对下一个元素的引用。在Aircraft类中,您应该有一个名为next的飞机类型属性,将您链接到列表中的下一架飞机。这允许您拨打myAircraft.next,因为您目前在代码中,这将允许您按顺序在列表中下移。我会让你自己找出其余的,这是作业,但如果你需要更多的解释,随时发表评论。

0

这里是一个链接,当他们说一个列表时,思考者提到了什么。这是链接http://www.algolist.net/Data_structures/Singly-linked_list/Traversal,解释列表。不过,我不确定这在java中是否具有代表性。你写的代码看起来像你没有排序,但在列表的最后添加了所有飞机。因此该列表未被排序。当你让temp.next = tail使列表中的最后一架飞机指向自身而不是null时。但是你不检查空值,你正在计算列表中的飞机数量。我发布了一个java示例,其中您有一个节点类,下一个节点,您应该添加节点尾,因为您的代码正在使用它。

1

除非您非常牢固地掌握OOP和引用类型,否则试图编写LinkedList实现是一种在受虐狂中的做法。

以下将会很长,可能会痛苦/羞辱。没关系,这将是一次很好的学习经历。我在这方面付出了很多努力,提供了彻底的评论和完整的实施。我建议你仔细阅读细节,直到你完全理解他们的目的。

首先,修好你的飞机班。既然你需要创建多个实例,静态成员将无法工作。如果你不明白为什么,花一些时间来刷新你的面向对象的基础知识。

列表节点应设计为存储最少的数据。在你的情况下,它看起来就像你在那里的大部分。有针对每个节点的航班数据和对列表中下一个项目的引用。这就是你需要的。

如果没有这些额外的克鲁夫特这里是什么样子:

public class Aircraft { 
    public String name; 
    public String type; 
    public int speed; 
    public int alt; 
    Aircraft next; 

    public Aircraft (String n, String t, int s, int a) { 
     name = n; 
     type = t; 
     speed = s; 
     alt = a; 
     next = null; 
    } 
} 

看起来不错。假设这具有内置的所有必要功能是安全的。

如果你想随意添加以下回复于:

  • 的setName()
  • 的getName()
  • 的setType()
  • 的getType()
  • setSpeed( )
  • getSpeed()
  • setAlt()
  • getAlt()

注:如果他们不设置为静态,这只会工作。除非你打算通过飞机实例被更改作为参数之一,每次你打电话给它。相信我,使用实例方法要容易得多。

变化:

  • 我删除了飞机()构造。至少,您需要使用至少一个航班号(或其他唯一标识符)初始化一个飞机节点,否则您将不能在稍后的列表中找到飞机。

  • removeName()是无用的。由于单个节点只知道列表中的下一个项目,因此它们无法自行删除。如果您使用了双向链接列表,其中每个节点都存储对之前的下一个节点的引用,那么这将是可能的,但实际上并不需要。 add()remove()*方法也是如此。添加/清除在** ATControl类中处理。

  • 没有太多需要GETNEXT()setNext()无论是。由于ATControl用于维护列表的状态(例如,大小,容量等),您不希望通过获取者/设置者公开访问nextCraft

现在对于ATControl:

public class ATControl { 
    private Aircraft head; // stores the start of the chain 
    private Aircraft tail; // stores the end of the chain 
    private int size; // stores the length of the chain 

    public ATControl() { 
     // ♫ "Started from the bottom now we're herre' ♫ 
     // Seriously, the list should start with nothing 
     head = null; 
     tail = null; 
     size = 0; 
    } 

    public void addFlight(String flight, String plane, int speed, int alt) { 
     // TODO: Implement this 
    } 

    public void removeFlight(String name) { 
     // TODO: Implement this 
    } 

    public void displayFlight(String name) { 
     // TODO: Use a foreach loop to find and display a flight 
    } 

    public void displayAll() { 
     // TODO: Use a foreach loop to display the flights here 
    } 
} 

变化:

  • 我删除了主*员,因为我没有丝毫的想法如何运作这里。无论哪种方式,要使用这个,你需要创建一个新的** ATControl实例。

  • 我删除了内联变量声明,因为它的实例成员必须在构造函数中设置。

  • 被初始化为null,因为没有飞机已被添加。

  • 我删除了飞机成员,因为它永远不会被使用。

  • 除非你只希望创建一个ATControl情况下,你不应该设置太静态两种。如果它们中的任何一个都被ATControl改变了,它会搞砸列表的内部状态,所以它们应该被设置为私有。

  • 我删除了大小限制,因为它没有必要做这个工作。如果需要,您可以稍后将其添加回来。

  • 我砍掉节点()addNodes()有两个原因。首先,它违反了SRP(单一责任原则),因为它们负责创建一个节点和一组节点。其次 - 我假设这是一个错误,但是 - 您要将航班号传递给您想要创建的节点数。例如,如果航班号是1457,那么你会在列表中添加1457个空节点。

  • 我改名addToList()addFlight(),以保持一致性。我还将其更名为showFlight()displayFlight()以保持一致性。为了简单起见,为了使这个类不仅仅是命令行输入,我还删除了用户输入部分。


我知道,我知道!我是一个无情的屠夫,但现在代码处于一个很好的位置,可以开始建立必要的功能。

第一件事第一件事。如果你不知道让一个类可迭代(即作为一个foreach循环工作),你将会发现。我需要添加更多的东西到ATControl,但它会很有趣。

public class ATControl implements Iterable { 
    private Aircraft head; 
    private Aircraft tail; 
    private int size; 

    public ATControl() { 
     head = null; 
     tail = null; 
     size = 0; 
    } 

    public void addFlight(String flight, String plane, int speed, int alt) { 
     // if the list is not currently empty 
     if (!isEmpty()) { 
      // store a reference to the last Aircraft in the list 
      Aircraft prev = tail; 
      // create a new aircraft and add it to the end of the list 
      tail = new Aircraft(flight, plane, speed, alt); 
      // link the old tail to the new tail 
      prev.next = tail; 
     } 
     // an empty list needs to be handled a little differently 
     else { 
      // notice, with no tail there's no tail to update 
      tail = new Aircraft(flight, plane, speed, alt); 
      // also, since there's only one item the head and tail are the same 
      head = tail; 
     } 
     size++; 
    } 

    // The hard part. Lots of nasty edge cases. 
    // Creating one of these from scratch will make your head hurt. 
    // Note: Setting variables to null marks them for the garbage collector. 
    // SideNote: With a doubly-linked list you can do removals within a foreach loop 
    public void removeFlight(String flight) { 
     Node prev = head; 
     Node curr = head; 
     // crawl the list looking for a match 
     while (curr.next != null || curr == tail) { 
      if (curr.flight.equals(flight)) { 
       // if there is only one item left, null everything 
       if (size == 1) { head = null; tail = null; } 
       // reset the head to start at the second Aircraft 
       else if (curr.equals(head)) { head = head.next; } 
       // reset the tail to end at the 2nd-to-last Aircraft 
       else if (curr.equals(tail)) { tail = prev; tail.next = null; } 
       // if it's in the middle, re-connect the broken links on either end 
       else { prev.next = curr.next; } 
       size--; 
       break; 
      } 
      prev = curr; 
      curr = prev.next; 
     } 
    } 

    public boolean isEmpty() { 
     return size == 0; // only returns true if size is 0 

    // The fun part. The following are necessary to make the list iterable 
    // Like magic, this class will now be callable as a foreach loop 
    public Iterator<Aircraft> iterator() { return new ATCIterator(); } 

    // This iterator code can be reused on any linked-list implementation 
    // Keep this handy in case you need to implement Iterable in the future 
    private class ATCIterator implements Iterator<Aircraft> { 
     private Aircraft current = head; 

     public Aircraft next() { 
      if (!hasNext()) { throw new NoSuchElementException(); } 
      Aircraft aircraft = current; 
      current = current.next; 
      return aircraft; 
     } 

     public boolean hasNext() { return current != null; } 

     // inline removals require a doubly linked list. To reconnect the break 
     // in the chain the node has to be aware of both the previous and next nodes. 
     public void remove() { throw new UnsupportedOperationException(); } 
    } 

    // lets put that foreach loop functionality to good use now. 

    // Bonus: use this to retrieve the matching Aircraft instance 
    // Once you have a reference to the Aircraft instance you can do things like 
    // get/set it's internal values. 
    public aircraft getFlight(String flight) { 
     for (Aircraft aircraft : this) 
      if (this.flight == flight) { 
       return this; 
    } 


    // displays the flight number of the first match 
    public void displayFlight(String flight) { 
     for (Aircraft aircraft : this) 
      if (this.flight == flight) { 
       System.out.printf("Flight: " + flight); 
       // Note: you can access the Aircraft details here via the 'this' keyword 
       return; 
    } 

    // crawls the whole list and displays the flight number of every aircraft 
    public void displayAll() { 
     for (Aircraft aircraft : this) 
      System.out.printf("Flight: " + flight); 
      // Note: you can access the flight details here via the 'this' keyword 
    } 
} 

所以,你的代码有很多的意见终日啃食在墙上。一些理论的时间。

什么让LinkedList成为LinkedList?

这实际上只是一堆对象实例,它们随机放置在堆上并通过引用(或针对C人群的指针)链接在一起。

想象一个LinkedList作为桑巴线

Samba Line

来源:The Traveling Eye Blog

注:双向链表,除了线可以改变方向相同。

每个人都紧盯着他们面前的人,但他们看不到他们身后的人。添加到列表就像添加一个人到行的前面。从技术上讲,我写的LinkedList作品的方向相反,添加的内容被添加到前端,删除从尾部删除,但概念是相同的。

从列表中提取/删除项目就像添加一个limbo杆。第一击从链条中取出,休息通过重新连接休息的两端来修补。

使用LinkedList的好处是它可以像你想要的一样大或小。然而,你可以自由地添加/删除节点。

不利之处在于,与数组不同,如果没有先行链接链接,就无法从列表中获取项目。而且,当列表变得非常大时,所有这些类实例和引用的开销开始变得昂贵。

在性能方面,需要O(1)(即恒定时间)来添加项目。 O(N)(即线性时间)从列表中提取/删除项目。并且,根据列表是单/双和/或跳转链接,涉及显着的内存开销。

还有其他的数据结构,如ArrayLists,HashMaps等,它们对像您这样的用例具有更好的性能或内存特性,但它们的编写/管理更加复杂。

在没有工作的情况下获得高级数据结构的所有神奇功能的最简单方法是打包和扩展现有的实现。例如,您可以创建一个在内部使用ArrayList进行数据存储的类。你甚至可以使用我上面演示的方法进行迭代。除了不是为任何通用类型编写的,它可以定制为使用您的飞机数据类型。

注意:如果您想学习如何编写数据结构,我建议您在线(或以其他方式)学习算法I类。

+0

好答案.. +1 – 2014-02-24 09:16:29