仅作为个人学习记录使用~
链表作为顺序表的链式存储一种实现方式,和顺序存储(数组)的实现相比要复杂一些,要想实现数组的存储首先需要对数组进行初始化,并且要设定好数组的容量,一旦容量不足就必须进行扩容操作。在单向链表中则不同,首先链表不需要像数组一样进行初始化,只需要指定头结点,一旦头结点设定好了,只需要在尾部进行插入操作就可以。要注意的是,链表的插入等操作必须依靠当前节点的前后两个节点,而前后节点的确定一定是从头结点开始,用指针一步一步往后移动。
package basic.practic;
public interface MyList {
public int getSize();
public boolean isEmpty();
public void insert(int i,Object e);
public boolean contains(Object obj);
public int indexOf(Object o);
public Object remove(Object o);
public Object remove(int i);
public Object get(int i);
public Object replace(int i,Object o);
public boolean insertBefore(Object p,Object e);
public boolean insertAfter(Object p,Object e);
}
package basic.practic;
/*
通过单向链表实现线性表
*/
public class MySingleLink implements MyList{
private Node head;//头结点
private int size;//保存元素的个数
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
/* if(size==0){
return false;
}
return true;*/
return size==0;
}
@Override
public void insert(int i, Object e) {
if(i<0||i>size){
throw new IndexOutOfBoundsException("空指针异常!");
}
// 创建一个结点
Node newnode = new Node(e,null);
// 头结点不存在
if(head==null){
head=newnode;
}else{
// 向索引位置0插入新结点
if(i==0){
newnode.next=head;
head=newnode;//刚插入的结点就是新的头结点
}else{
// 插入结点,必须先找到i-1这个结点,注意,每次都是从头开始找结点
Node pnode=head;
for(int j=1;j<i;j++){
pnode=pnode.next;
}
newnode.next=pnode.next;//注意先后顺序!
pnode.next=newnode;
}
}
size++;
}
@Override
public boolean contains(Object obj) {
/* if(indexOf(obj)>=0){
return true;
}
return false;*/
return indexOf(obj)>=0;
}
@Override
public int indexOf(Object o) {
Node pnode = head;
int i=0;
while(pnode.next!=null){
if(o==null&&pnode.data==null){
return i;
}else if(o!=null&&o.equals(pnode.data)){
return i;
}
i++;
pnode=pnode.next;
}
return -1;
}
@Override
public Object remove(Object o) {
int index=indexOf(o);
if(index<0){
throw new RuntimeException("数组中不存在该元素");
}
Node pnode=head;
return remove(index);
}
@Override
public Object remove(int i) {
if(i<0||i>=size){
throw new IndexOutOfBoundsException("越界");
}
Node pnode=head;
if(i==0){
head=head.next;
size--;
return pnode.data;
}
else{
for(int j=1;j<i;j++){
pnode=pnode.next;
}
Object old=pnode.next.data;//保存删除结点的数据
pnode.next=pnode.next.next;//修改i-1结点的指针,指向i+1结点
size--;
return old;
}
}
@Override
public Object get(int i) {
if(i<0||i>=size){
return null;
}
Node pnode=head;
for(int j=1;j<i;j++){
pnode=pnode.next;
}
return pnode.next.data;
}
@Override
public Object replace(int i, Object o) {
if(i<0||i>=size){
return null;
}
Node pnode=head;
insert(i,o);
return o;
}
@Override
public boolean insertBefore(Object p, Object e) {
if(contains(p)){
insert(indexOf(p),e);
return true;
}
return false;
}
@Override
public boolean insertAfter(Object p, Object e) {
if(contains(p)){
insert(indexOf(p)+1,e);
return true;
}
return false;
}
// 定义一个内部类来表示单向链表中的结点
private class Node {
private Object data;//保存结点中的数据
private Node next;//保存下个结点的引用
public Node(Object data, Node next) {
this.data = data;
this.next = next;
}
}
@Override
public String toString() {
StringBuilder sb=new StringBuilder();
sb.append("[");
Node pnode=head;
while(pnode!=null){
sb.append(pnode.data);
if(pnode.next!=null){
sb.append(",");
}
pnode=pnode.next;
}
sb.append("]");
return sb.toString();
}
}
package basic.practic;
public class MySingleLinkTest {
public static void main(String[] args) {
MySingleLink m=new MySingleLink();
System.out.println(m.getSize());//0
System.out.println(m.isEmpty());//true
m.insert(0,"tom");
m.insert(0,"jack");
m.insert(0,"rose");
m.insert(0,"lily");
System.out.println(m);//[tom,jack,rose,lily]
/*System.out.println(m.indexOf("jack"));//1
System.out.println(m.contains("jack"));//true
System.out.println(m.remove(1));//jack
System.out.println(m);*///[tom,rose,lily]
System.out.println(m.get(1));//rose
System.out.println(m.replace(1,"lucy"));//lucy
System.out.println(m);//[lily,lucy,rose,jack,tom]
System.out.println(m.insertAfter("lucy","mary"));//true
System.out.println(m);//[lily,lucy,mary,rose,jack,tom]
System.out.println(m.insertBefore("mary","john"));//true
System.out.println(m);//[lily,lucy,john,mary,rose,jack,tom]
}
}