私は試験のために勉強しています、そしてこれは古いテストからの問題です:
次の宣言を持つリストヘッドを持つ単一リンクリストがあります。
_class Node {
Object data;
Node next;
Node(Object d,Node n) {
data = d;
next = n;
}
}
_
リストの最後にx
を追加するメソッドvoid addLast(Node header, Object x)
を記述します。
私が実際に次のようなものを持っていた場合、私は知っています:
_LinkedList someList = new LinkedList();
_
次のようにして、最後にアイテムを追加するだけです。
_list.addLast(x);
_
しかし、どうすればここでそれを行うことができますか?
class Node {
Object data;
Node next;
Node(Object d,Node n) {
data = d ;
next = n ;
}
public static Node addLast(Node header, Object x) {
// save the reference to the header so we can return it.
Node ret = header;
// check base case, header is null.
if (header == null) {
return new Node(x, null);
}
// loop until we find the end of the list
while ((header.next != null)) {
header = header.next;
}
// set the new node to the Object x, next will be null.
header.next = new Node(x, null);
return ret;
}
}
ループを使用してリンクリスト全体をナビゲートし、各ノードの「次の」値を確認する必要があります。最後のノードは、次の値がnullのノードになります。このノードの次の値を、入力データを使用して作成する新しいノードにするだけです。
node temp = first; // starts with the first node.
while (temp.next != null)
{
temp = temp.next;
}
temp.next = new Node(header, x);
それが基本的な考え方です。もちろん、これは擬似コードですが、実装するのに十分単純なはずです。
public static Node insertNodeAtTail(Node head,Object data) {
Node node = new Node(data);
node.next = null;
if (head == null){
return node;
}
else{
Node temp = head;
while(temp.next != null){
temp = temp.next;
}
temp.next = node;
return head;
}
}
テールノードを追跡している場合は、リスト内のすべての要素をループする必要はありません。
新しいノードを指すようにテールを更新するだけです。
AddValueToListEnd(value) {
var node = new Node(value);
if(!this.head) {
this.head = node;
} else {
this.tail.next = node;
}
this.tail = node;
}
平易な英語で:
これがリンクリストクラスの部分的な解決策です。実装の残りの部分はあなたに任せました。また、リンクリストの一部としてテールノードを追加するという良い提案も残しました。
ノードファイル:
public class Node
{
private Object data;
private Node next;
public Node(Object d)
{
data = d ;
next = null;
}
public Object GetItem()
{
return data;
}
public Node GetNext()
{
return next;
}
public void SetNext(Node toAppend)
{
next = toAppend;
}
}
そしてここにリンクリストファイルがあります:
public class LL
{
private Node head;
public LL()
{
head = null;
}
public void AddToEnd(String x)
{
Node current = head;
// as you mentioned, this is the base case
if(current == null) {
head = new Node(x);
head.SetNext(null);
}
// you should understand this part thoroughly :
// this is the code that traverses the list.
// the germane thing to see is that when the
// link to the next node is null, we are at the
// end of the list.
else {
while(current.GetNext() != null)
current = current.GetNext();
// add new node at the end
Node toAppend = new Node(x);
current.SetNext(toAppend);
}
}
}
nullへの次のポインタを持つリンクリストの最後の要素にループし、data = objectとnextpointer = nullを持つ新しいノードを指すように次のポインタを変更します
AddLast()内のwhileループはO(n)複雑であるため、addLast()には最適化が必要です。以下はLinkedListの実装です。ll.addLastx(i)を使用してコードを1回実行し、 ll.addLast(i)で再度実行すると、addLast()とaddLast()の処理時間に大きな違いがあることがわかります。
Node.Java
package in.datastructure.Java.LinkedList;
/**
* Created by abhishek.panda on 07/07/17.
*/
public final class Node {
int data;
Node next;
Node (int data){
this.data = data;
}
public String toString(){
return this.data+"--"+ this.next;
}
}
LinkedList.Java
package in.datastructure.Java.LinkedList;
import Java.util.ArrayList;
import Java.util.Date;
public class LinkedList {
Node head;
Node lastx;
/**
* @description To append node at end looping all nodes from head
* @param data
*/
public void addLast(int data){
if(head == null){
head = new Node(data);
return;
}
Node last = head;
while(last.next != null) {
last = last.next;
}
last.next = new Node(data);
}
/**
* @description This keep track on last node and append to it
* @param data
*/
public void addLastx(int data){
if(head == null){
head = new Node(data);
lastx = head;
return;
}
if(lastx.next == null){
lastx.next = new Node(data);
lastx = lastx.next;
}
}
public String toString(){
ArrayList<Integer> arrayList = new ArrayList<Integer>(10);
Node current = head;
while(current.next != null) {
arrayList.add(current.data);
current = current.next;
}
if(current.next == null) {
arrayList.add(current.data);
}
return arrayList.toString();
}
public static void main(String[] args) {
LinkedList ll = new LinkedList();
/**
* @description Checking the code optimization of append code
*/
Date startTime = new Date();
for (int i = 0 ; i < 100000 ; i++){
ll.addLastx(i);
}
Date endTime = new Date();
System.out.println("To total processing time : " + (endTime.getTime()-startTime.getTime()));
System.out.println(ll.toString());
}
}
ここにヒントがあります。リンクリスト内のノードのグラフがあり、linkedList内の最初のノードであるheadへの参照を常に保持しています。
nextはリンクリスト内の次のノードを指しているため、nextがnullの場合、リストの最後になります。
上記のプログラムでは、NullPointerExceptionが発生する可能性があります。これは、linkedListの最後に要素を追加する簡単な方法です。
public class LinkedList {
Node head;
public static class Node{
int data;
Node next;
Node(int item){
data = item;
next = null;
}
}
public static void main(String args[]){
LinkedList ll = new LinkedList();
ll.head = new Node(1);
Node second = new Node(2);
Node third = new Node(3);
Node fourth = new Node(4);
ll.head.next = second;
second.next = third;
third.next = fourth;
fourth.next = null;
ll.printList();
System.out.println("Add element 100 to the last");
ll.addLast(100);
ll.printList();
}
public void printList(){
Node t = head;
while(n != null){
System.out.println(t.data);
t = t.next;
}
}
public void addLast(int item){
Node new_item = new Node(item);
if(head == null){
head = new_item;
return;
}
new_item.next = null;
Node last = head;
Node temp = null;
while(last != null){
if(last != null)
temp = last;
last = last.next;
}
temp.next = new_item;
return;
}
}