链表:
- 链表 与 数组区别:
- 数组:长度固定 / 连续的空间 / 下标操作快
- 链表:长度可变 / 不连续 / 增加数据快/删除数据快/遍历慢/查找数据慢
- 结构变化更灵活
节点:
- 一个数据存储域
- 指向其他节点的 引用/指针
首先,设置一个节点类,每个节点拥有自身内容和指向下一个节点的指针两个属性,并增加它们的获取和判断方法。
class Node<E>{
private Object e;
private Node next;
public Node(E e, Node next){
this.e = e;
this.next = next;
}
public boolean next(){
return next != null;
}
public E getValue(){
return (E) e;
}
public Node getNext() {
return next;
}
public void setNext(Node next){
this.next = next;
}
}
接下来,就可以开始写链表类。先把基本的属性和构造方法写好。
public class MyLinkedList<E> implements List<E>{
Node<E> root;
int length;
int size;
// Node<E> last;
public MyLinkedList(){
}
值得一提的是,我这里写了一个接口List用来规范这些链表。
public interface List<E>{
int size();
void add(E e);
void addAll(List<E> otherList);
E get(int index);
boolean contains(E e);
boolean containsAll(E e);
E remove(int index);
void remove(E e);
void removeAll(List<E> eList);
void set(int index, E e);
Object[] toArray();
}
因此,MyLinkedList类里就改写这些方法。
@Override
public int size(){
return size;
}
@Override
public void add(E e){
if(root == null){
root = new Node<E> (e, null);
length++;
size++;
return;
}
// 尾插法
// 顺着链表 遍历找到为空的节点 实例化一个节点对象 存储进去
Node<E> tempNode = root;
while(tempNode.next ()){
tempNode = tempNode.getNext ();
}
Node<E> next = tempNode.getNext ();
next = new Node<> (e, null);
tempNode.setNext (next);
length++;
size++;
}
@Override
public void addAll(List<E> otherList){
// 类型判断
if(otherList instanceof MyLinkedList<E>){
MyLinkedList<E> newList=(MyLinkedList<E>)otherList;
// 节点相连
Node<E> pnode=newList.root;
for(int i = 0; i < newList.size; i++){
add(pnode.getValue());
if(pnode.next()){
pnode=pnode.getNext();
}
}
}else{
MyArrayList<E> newList=(MyArrayList<E>)otherList;
for(int i=0;i<newList.getIndex();i++){
add((E) newList.getfi(i));
}
// 将数组中元素一个添加过来
}
}
@Override
public E get(int index) {
return null;
}
@Override
public boolean contains(E e){
Object pe=root.getValue();
Node<E> pnode=root;
if (pe.equals(e)){return true;};
while (pnode.next()){
if(!pe.equals(e)){
pnode=pnode.getNext();
}else {
return true;
}
}
if (pe.equals(e)){return true;};
return false;
}
@Override
public boolean containsAll(E e){
return false;
}
@Override
public E remove(int index){
return null;
}
@Override
public void remove(E e){
Node<E> pnode=root;
if(pnode.getValue().equals(e)){
root = pnode.getNext();
}
while (pnode.getNext().next()){//如果当前节点存在下两个
if(pnode.getNext().getValue().equals(e)){//下一个节点等于e
pnode.setNext(pnode.getNext().getNext());//则当前节点直接连接下下个节点
length--;
size--;
}else{//下一个节点不等于e
pnode=pnode.getNext();//则向后遍历
}
}
if (pnode.next()){//当前节点后面只剩一个
if (pnode.getNext().getValue().equals(e)){//如果后面那个节点等于e
pnode.setNext(null);
length--;
size--;
}
}else {//如果当前链表只有这一个节点
root=null;
length=0;
size=0;
}
}
@Override
public void removeAll(List<E> eList){
if(eList instanceof MyLinkedList<E>){
MyLinkedList<E> newList=(MyLinkedList<E>)eList;
// 节点相连
Node<E> pnode=newList.root;
for(int i = 0; i < newList.size; i++){
remove(pnode.getValue());
if(pnode.next()){
pnode=pnode.getNext();
}
}
}else {
MyArrayList<E> newList = (MyArrayList<E>) eList;
for (int i = 0; i < newList.getIndex(); i++) {
remove((E) newList.getValues()[i]);
}
}
}
// 插入
@Override
public void set(int index, E e){
if(index>size-1){
System.out.println("输入超出链表长度");
return;
}
Node<E> pnode=root;
Node<E> newnode=new Node<E>(e,null);
for(int i = 0; i < size; i++){
pnode=pnode.getNext();
}
//到达index-1位置节点
if(pnode.next()){
newnode.setNext(pnode.getNext());
}
pnode.setNext(newnode);
}
public Object[] toArray(){
Node<E> pnode=root;
Object[] arr = new Object[size];
for(int i = 0; i < size-1; i++){
arr[i]=pnode.getValue();
pnode=pnode.getNext();
}
arr[size-1]=pnode.getValue();
return arr;
}
@Override
public String toString(){
Node<E> pnode=root;
String s="";
for(int i = 0; i < size-1; i++){
s+=pnode.getValue().toString();
pnode=pnode.getNext();
}
s+=pnode.getValue().toString();
return s;
}
最后,对这些方法进行测试。
public static void main(String[] args) {
MyLinkedList<Integer> list1=new MyLinkedList<>();
MyLinkedList<Integer> list2=new MyLinkedList<>();
MyLinkedList<Integer> list3=new MyLinkedList<>();
list1.add(new Integer(1));
list1.add(new Integer(2));
list1.add(new Integer(3));
list2.add(new Integer(1));
list2.add(new Integer(2));
list2.add(new Integer(3));
list3.add(new Integer(4));
list3.add(new Integer(5));
list3.add(new Integer(6));
System.out.println(list1.toString());
System.out.println(list1.equals(list2));
System.out.println(list1.equals(list3));
list3.addAll(list1);
list3.addAll(list2);
System.out.println(list3.contains(new Integer(1)));
list3.remove(new Integer(1));
System.out.println(list3.toString());
list3.removeAll(list1);
System.out.println(list3.toString());
}
测试结果:
123
false
false
false
4562323
456
因此这个复现还是不错滴