Java 用单链表实现线性表(增、删、改、查、遍历等)
用数组和单链表实现线性表的区别:
数组更好上手,遍历范围更好控制,但是添加新的信息都要重新创建一个新数组,比较麻烦。具体可以参考这个链接:
link.
单链表比较难上手,特别是遍历链表和删除节点比较难搞,但是添加新的信息比较简单,找空的节点插入就好。单链表可以参考这个链接:
link
Mylinklist的定义、Node类定义和构造函数
public class MyLinkList <E>{
private static final int defaultLength = 1;
private int length=1; //容量 容量=下标+1
private MyNode<E> head; //头指针 空的
public class Node{
private int size ; //下标
private E value;
private Node next;
public Node(){
size =0;
value = null;
next =null;
}
public Node(E e, int newsize){
value = e;
size =newsize;
next =null;
}
public Node(E e){
value =e;
next =null;
}
public Node(int newsize){
value = null;
size =newsize;
next =null;
}
public void addNode(Node node){
next =node;
length++;
}
public void addValue(E e){
this.value =e;
}
}
Mylinklist构造函数
/**
* 默认构造函数
*/
public MyLinkList(){
length =1;
head =new MyNode<E>();
}
/**
* 用数字构造空线性表
* @param number
*/
public MyLinkList(int number){
length =number+1;
head =new MyNode<E>();
MyNode<E> node =head;
int size =1;
for (int i=0; i<number;i++){
MyNode<E> newnode =new MyNode<E>(size);
node.addNode(newnode);
node =node.next;
size++;
}
}//根据传入数据 初始化
/**
* 根据传入链表构造
* @param newNode
*/
public MyLinkList(MyNode<E> newNode){
head =new MyNode<E>();
MyNode<E> node =head;
head.next =newNode;
this.sortSize();
}
增:添加新的信息(E是泛型,根据外部传入数据类型变化)
/**
*在空的地方插入数据
* @param data
*/
public void addOneData(E data){
MyNode<E> node =head; //从头节点之后插入
while (true){
if (node.next ==null){
int newszie = node.size+1; //这个怎么可以访问呢
MyNode<E> newNode = new MyNode<E>(data, newszie);
node.addNode(newNode);
length++;
//System.out.println("添加了新的数据"+newNode.value);
break;
}//如果是最后一个,添加新的节点
if(node.value ==null&&node.size!=0){
node.value =data;
break;
}//确认不是头节点
node =node.next;
}
}
/**
* 添加新的链表到尾部
* @param newNode
*/
public void add (MyNode<E> newNode){
if (this.head ==null){
head =new MyNode<E>();
//head.print();
}
MyNode<E> node =head;
while (true){
if (node.next ==null){
System.out.println("最后一位是"+node.size);
node.addNode(newNode);
node.print();
break;
}//最后一个
//System.out.println("下标1"+node.size);
node=node.next;
}
this.sortSize();
}
删:根据下标、元素、链表删除数据
/**
* 根据下标删除元素
* @param number
*/
public void remove(int number){
if (number >(length-1)){
System.err.println("输入超出范围");
}
MyNode<E> node =head;
while (true){
if (node.next ==null){
break;
}//最后一个节点
if (node.next.size ==number){
System.out.println("要删除的数字"+number +" 下标"+node.next.value);
MyNode<E> newnode = node.next.next;
if(newnode ==null){
node.next =null;
length--;
break;
}else{
newnode.size = node.next.size;
node.next =newnode;
length--;
}
}//中间节点和倒数第二个节点(),包括删除最后一个节点
node =node.next;
}
this.sortSize();
}
/**
* 根据元素获取多个下标,然后移位
* @param e
*/
public void remove(E e){
MyNode<E> node =head;
while (true){
if (node.next != null){
if (node.next.value ==e){
MyNode<E> newnode = node.next.next;
System.out.println("要删除的数字"+e +" 下标"+node.next.size);
newnode.size = node.next.size;
node.next =newnode;
length--;
}//中间节点和倒数第二个节点(),包括删除最后一个节点
}//不是最后一个节点
if (node.next ==null){
break;
}//最后一个节点
node =node.next;
}
this.sortSize();
}
/**
* 根据链表,删除所有重复数据
*/
public void remove(MyNode<E> myNode){
//默认不是空的链表
MyNode<E> headNode =this.head;
while (true){
while (true){
if (headNode.next.value == myNode.value ){
MyNode<E> node1 =headNode.next.next;
headNode.next =node1;
break;
}
if (headNode.next ==null){
break;
}
headNode =headNode.next;
}// headnode循环
if (myNode.next ==null){
break;
}
myNode= myNode.next;
}
this.sortSize();
}
查:根据下标得到元素,根据元素获取多个下标
//根据下标获取元素
public E get(int number){
if (number >(length-1)){
System.err.println("输入超出范围");
}
MyNode<E> node =head;
while (true){
if(node.size ==number){
return node.value;
}
if (node.next ==null){
System.out.println("下标对应的元素为空");
break;
}//最后一个,
node =node.next;
}
return null;
}
/**
*根据元素获取多个下标
* @param element
* @return int[]
*/
public int[] get(E element){
MyNode<E> node =head;
int number=0;
while (true){
if (node.next ==null){
if(node.value==element){
System.out.println("元素的位子"+node.size);
number++;
}
if (number ==0){
System.err.println("没有这个元素");
return null;
}
break;
}//最后一个
if(node.value ==element){
System.out.println("元素的位子"+node.size);
number++;
}
node =node.next;
}
//已经找到了对应的元素
System.out.println();
System.out.println("个数"+number);
int[] numbers =new int[number];
node =head;
int i=0;
while (true){
if (node.next ==null){
if(node.value==element){
numbers[i] =node.size;
}
break;
}//最后一个
if(node.value== element){
numbers[i] =node.size;
i++;
}
node =node.next;
}
return numbers;
}
打印:遍历线性表
/**
*打印出所有的元素
* @param
* @return
*/
public void print(){
MyNode<E> node =head;
System.out.println("下标"+node.size+" 头节点,数据是空的");
node=node.next;
while (true){
if (node.next ==null){
System.out.println("下标"+node.size+" 数据"+node.value);
break;
}//找到最后一个
System.out.println("下标"+node.size+" 数据"+node.value);
node =node.next;
}
}
排序:根据前后顺序整理下标(从头节点到尾节点)
因为删除节点之后,剩下节点的下标会发生变化,所以需要重新排序
/**
* 用于删除节点之后重新排序
*/
public void sortSize(){
MyNode<E> node =head;
int newsize =0;
while (true){
if (node.size!=newsize){
node.size =newsize;
}
node=node.next;
newsize++;
if (node.next ==null){
node.size =newsize;
break;
}//最后一个
}
}