使用迭代器(Iterator)來實現連結串列的相關操作
阿新 • • 發佈:2019-01-04
在這一篇裡,要講的是如何使用迭代器對連結串列進行相關的操作,比如刪除,獲取,插入等操作,那首先介紹一下什麼是迭代器,java裡面的迭代器的實用性很大,在我們實際對連結串列進行刪除操作時,如果是要對某個限制條件下的所有連結串列資料都刪除,如果是用普通的指標,那就必須每次都對連結串列進行遍歷查詢,符合了條件進行刪除,而效率很低,而不像陣列,有固定的下標位,所以我們設法給予一個類似陣列下標的東西來表明連結串列的位置。
這時我們使用了一種類,叫迭代器類,迭代器類包含對資料結構的資料項的引用,並用來遍歷這些結構的物件。
好了,大概介紹了一下,我們來看看迭代器的具體使用吧:
這裡筆者用迭代器去代替一些連結串列操作,也就是這些操作可以在連結串列裡執行的,但是放在迭代器裡能更加明白其用法,首先建立一個連結串列:
<span style="font-size:18px;">public class Link {
private long dData;
private Link next;
public Link(long dd){
dData = dd;
}
public void displayLink(){
System.out.print(dData + " ");
}
}</span>
這裡有long型的資料,也有next的引用,作為標識下個鏈節點的引用,然後我們來建立連結串列:
<span style="font-size:18px;">public class LinkList { private Link first; public LinkList(){ first = null; //建構函式初始化首節點 } public Link getFirst() { //獲取第一個節點 return first; } public void setFirst(Link first) { //設定第一個節點 this.first = first; } public boolean isEmpty(){ //判斷連結串列是否為空 return (first == null); } public LinkIterator myIterator(){ //定義迭代器,與之聯絡起來 return new LinkIterator(this); } public void displayLinklist(){ //打印出連結串列中的元素 Link current = first; while (current != null) { System.out.print(current.dData + " "); current = current.next; } System.out.println(""); } }</span>
其他函式沒什麼好說的,主要要注意一下關於連結串列和迭代器之間的聯絡,在連結串列中建立迭代器時,傳遞給迭代器一個引用,這個引用儲存在迭代器的一個欄位中,這樣迭代器就可以訪問連結串列中的私有資料欄位了。
然後是迭代器類的實現:
這個迭代器類實現要注意節點直接的關係,注意判斷節點的位置和表是否為空,這兩點經常會忘記。然後就是主要函式的呼叫了,這裡筆者分為幾個操作進行功能的呼叫:public class LinkIterator { private Link current; private Link previous; private LinkList outlist; public LinkIterator(LinkList mLinkList){ //建構函式,同時進行將迭代器置於表頭 outlist = mLinkList; reset(); } public void reset(){ //將迭代器置於表頭方法 current = outlist.getFirst(); previous = null; } public boolean atEnd(){ //判斷迭代器是否位置在表尾 return (current.next == null); } public void nextLink(){ //將迭代器的位置向後移動一位 previous = current; current = current.next; } public Link getCurrent(){ //返回此時迭代器所指鏈節點的值 return current; } public void inserAfter(long dd){ //插入迭代器所指鏈節點的後面 Link newLink = new Link(dd); if (outlist.isEmpty()) { outlist.setFirst(newLink); current = newLink; } else { newLink.next = current.next; current.next = newLink; nextLink(); } } public void insertBefore(long dd){ //插入迭代器所指鏈節點對的前面 Link newlink = new Link(dd); if (previous == null) { newlink.next = outlist.getFirst(); outlist.setFirst(newlink); reset(); }else { newlink.next = previous.next; previous.next = newlink; current = newlink; } } public long deleteLink(){ //刪除迭代器所指的鏈節點 long data = current.dData; if (previous == null) { outlist.setFirst(current.next); reset(); }else { previous.next = current.next; if (atEnd()) { reset(); }else { current = current.next; } } return data; } }
public class IteratorTest {
public static void main(String[] args) throws IOException {
LinkList mLinkList = new LinkList();
LinkIterator mIterator = mLinkList.myIterator();
long value;
mIterator.inserAfter(20);
mIterator.inserAfter(40);
mIterator.inserAfter(80);
mIterator.insertBefore(60);
while (true) {
System.out.println("please input the letter to operate the Iterator: ");
System.out.println("you can input the word of s,r,g,n,b,a,d: ");
System.out.flush();
int m = getChar();
switch (m) {
case 's':
if (!mLinkList.isEmpty()) {
mLinkList.displayLinklist();
}else {
System.out.println("the linklist is empty");
}
break;
case 'r':
mIterator.reset();
break;
case 'g':
if (!mLinkList.isEmpty()) {
value = mIterator.getCurrent().dData;
System.out.println("Return data is : " + value);
}else {
System.out.println("the linklist is empty");
}
break;
case 'n':
if (!mLinkList.isEmpty() && !mIterator.atEnd()) {
mIterator.nextLink();
}else {
System.out.println("something happening");
}
break;
case 'b':
if (!mLinkList.isEmpty()) {
System.out.print("input the word you want to insert ");
System.out.flush();
value = getInt();
mIterator.insertBefore(value);
}else {
System.out.println("something happening");
}
break;
case 'a':
if (!mLinkList.isEmpty()) {
System.out.print("input the word you want to insert ");
System.out.flush();
value = getInt();
mIterator.inserAfter(value);
}else {
System.out.println("something happening");
}
break;
case 'd':
if (!mLinkList.isEmpty()) {
value = mIterator.deleteLink();
System.out.print("the deleted data is : " + value);
}else {
System.out.println("something happening");
}
break;
default:
System.out.println("Invalid entry");
break;
}
}//end while
}//end main
public static String getString() throws IOException{
InputStreamReader inReader = new InputStreamReader(System.in);
BufferedReader buf = new BufferedReader(inReader);
String mString = buf.readLine();
return mString;
}
public static char getChar() throws IOException{
char a;
a = getString().charAt(0);
return a;
}
public static int getInt() throws IOException{
int a ;
String s = getString();
a = Integer.parseInt(s);
return a;
}
}
主函式的呼叫要注意對錶是否為空的判斷,以及對迭代器位置的判斷,如果為空或者在尾部,應該做出相應的處理,這裡更好應該在方法中就進行自動的判斷,筆者在這裡實現的是單鏈表,大家可以去嘗試實現以下雙向連結串列是如何實現的。
下面是執行結果:
好了,迭代器就講到這裡,大家有疑問可以評論。