java算法判断链表有没有闭环_前端算法系列之二:数据结构链表、双向链表、闭环链表、有序链表...
前言
上一次我們講到了數據結構:棧和隊列,并對他們的運用做了一些介紹和案例實踐;我們也講到了怎么簡單的實現一個四則運算、怎么去判斷標簽是否閉合完全等等,anyway,今天接著和大家介紹一些數據結構:
鏈表
鏈表是一種怎么樣的結構呢?鏈表就是一種可以把數據串聯起來的結構,每個元素會有指向下一個元素的指針(末尾的沒有普通鏈表),就像現實世界中的火車一樣一節一節的串聯起來;鏈表根據自身的指針指向又可以分為:單向鏈表、雙向鏈表、循環鏈表;
鏈表首先會有一個表頭,表頭作為起始的指針,然后每一個元素我們稱作為節點(node);每個節點有一個指向下一個節點的指針(next),直到鏈表的末尾指針會指向undefined;
鏈表的實現
1、節點
節點的創建和定義;每個節點會有一個保存自己數據的屬性(element),然后有一個指針(next)export?class?Node?{
constructor(element,?next?=?null)?{
this.element?=?element;
this.next?=?next;
}
}
2、鏈表的api
getElementAt(position): 獲取某個位置的元素
append(element): 向鏈表末尾中添加元素
removeAt(idx): 移除某個元素
insert(element, position = 0, dir = 'before'): 向指定位置添加元素
insertAfter(element, position): 向指定的位置后面添加元素
size(): 鏈表的長度
remove(): 刪除鏈表末端元素
removeAll(): 刪除整個鏈表
isEmpty(): 檢查鏈表是否為空import?{?defaultEquals?}?from?"../util.js";
import?{?Node?}?from?'./Node.js'
export?default?class?LinkedList?{
constructor(equalsFn?=?defaultEquals)?{
this.count?=?0;
this.head?=?null;
this.equalsFn?=?equalsFn;
}
getElementAt(position)?{
if(position?>=?0?&&?position?<=?this.count)?{
let?node?=?this.head;
for?(let?i?=?0;?i?
node?=?node.next;
}
return?node;
}
return?undefined;
}
insertAfter(element,?position)?{
return?this.insert(element,?position,?'after');
}
size()?{
return?this.count;
}
remove()?{
return?this.removeAt(this.size()?-?1);
}
removeAll()?{
this.count?=?0;
this.head?=?null;
}
isEmpty()?{
return?this.size()?===?0;
}
getHead()?{
return?this.head;
}
}
3、鏈表末尾添加一個元素append;append(element)?{
const?node?=?new?Node(element);
let?current?=?this.head;
if(current?==?null)?{
this.head?=?node;
}?else?{
current?=?this.head;
while?(current.next?!=??null)?{
current?=?current.next;
}
current.next?=?node
}
this.count++;
return?element;
}
4、插入一個元素insert(element,?position?=?0,?dir?=?'before')?{
if?(element?===?undefined)?{
throw?Error('缺少需要插入的元素');
return;
}
if?(position?>=?this.count)?{
return?this.append(element);
}
const?node?=?new?Node(element);
const?targetNode?=?dir?===?'before'???this.getElementAt(position?-?1)?:?this.getElementAt(position);
if?(!targetNode)?{
let?prev?=?this.head;
this.head?=?node;
node.next?=?prev;
}?else?{
let?next;
next?=?targetNode.next
targetNode.next?=?node;
node.next?=?next;
}
this.count++;
return?element;
}
5、刪除一個元素removeAt(idx)?{
if?(idx?>=?0?&&?idx?
let?current?=?this.head;
if?(idx?===?0)?{
this.head?=?current.next;
current.next?=?null;
}?else?{
let?prev?=?this.getElementAt(idx?-?1);
current?=?prev.next;
prev.next?=?current.next;
}
this.count--;
return?current.element;
}
return?undefined;
}
6、雙向鏈表
單向鏈表元素指向都是一個方向的,也只能被單向遞歸搜索,而雙向鏈表不僅僅有指向下一個元素的指針同時具有指向上一個元素的指針;
import?LinkedList?from?"./LinkedList";
import?{defaultEquals}?from?"../util";
import?{?DoubleNode?}?from?"./DoubleNode";
export?default?class?DoubleLinkedList?extends?LinkedList{
constructor(equalIsFn?=?defaultEquals){
super(equalIsFn);
this.tail?=?null;//?隊列尾部
}
getElementAt(position)?{
if(position?>=?0?&&?position?<=?this.count)?{
if?(position?>?this.count/2)?{
let?cur?=?this.tail;
for?(let?i?=?this.count?-?1;?i?>?position;?i--){
cur?=?cur.prev;
}
return?cur;
}?else?{
return?super.getElementAt(position)
}
}
return?undefined;
}
removeAll()?{
super.removeAll();
this.tail?=?null;
}
removeAt(position)?{
if?(position?>=?0?&&?position?
let?cur?=?this.getElementAt(position);
if(position?===?0)?{
this.head?=?cur.next;
cur.next?=?null;
this.prev?=?null;
}?else?if?(position?===?this.count?-?1)?{
this.tail?=?cur.prev;
this.tail.next?=?null;
cur.prev?=?null;
}?else?{
let?prev?=?cur.prev;
let?next?=?cur.next;
prev.next?=?next;
next.prev?=?prev;
cur.prev?=?null;
cur.next?=?null;
}
this.count--;
return?cur.element;
}
return?undefined;
}
}
隊列末尾插入元素(append)
雙向鏈表插入元素和單向比較類似,不同的是雙向不僅要鏈接他的下級還得關聯他的前一級;append(element)?{
const?node?=?new?DoubleNode(element);
if?(!this.tail)?{
this.head?=?node;
this.tail?=?node;
}?else?{
let?cur?=?this.tail;
cur.next?=?node;
node.prev?=?cur;
this.tail?=?node;
}
this.count++;
return?element;
}
中間某個位置插入元素insert(element,?position?=?0,?dir?=?'before'){
if?(element?===?undefined)?{
throw?Error('缺少需要插入的元素');
return;
}
if?(position?>=?this.count)?{
return?this.append(element);
}
const?node?=?new?DoubleNode(element);
let?cur;
const?targetNode?=?dir?===?'before'???this.getElementAt(position?-?1)?:?this.getElementAt(position);
if?(!targetNode)?{
cur?=?this.head;
node.next?=?cur;
cur.prev?=?node;
this.head?=?node;
}?else?{
let?next;
next?=?targetNode.next
targetNode.next?=?node;
node.prev?=?targetNode;
node.next?=?next;
next.prev?=?node;
}
this.count++;
return?element;
}
移除某個元素也是上述相同,修改節點的前后指針就可以了,這里不再贅述,詳情看源碼
閉環鏈表
閉環鏈表也稱環,是一個閉合的結構,尾部會指向頭部
有序鏈表
有序鏈表就是在append元素的時候進行排序加入從而得到一個有順序的鏈表,比較函數可以根據實例化的時候傳入比較函數equalIsFn;
總結
以上是生活随笔為你收集整理的java算法判断链表有没有闭环_前端算法系列之二:数据结构链表、双向链表、闭环链表、有序链表...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android开源tabview,Tab
- 下一篇: 设计java application程序