链表作为线性表的半壁江山,链表与顺序表的逻辑结构是相同的,但是存储结构却不一样。以单链表为代表分析:
- 顺序表需要一块连续的内存空间,当我们已知这块内存的起始位置时,可以根据线性表的特性很容易拿到每一个位置的值
- 单链表在内存中则不一定是连续的,每个节点都会牺牲一定的空间来存放下一个节点的位置,这样无限套娃下去便形成了一种链式结构。由其特性不难知道:链表不能由起始位置直接推断出剩下节点的位置,只能顺藤摸瓜慢慢找。单链表中每个节点已知的信息只有自己的节点值与自己的下一个节点的位置,其余信息一概不知。
package com.day06;
/**
* Linked list
*/
public class day06_LinkList {
/**
* length 属性是链表的长度 初始值为0
* 内部类 Node*/
int length=0;
class Node{
/**
* data属性 是链表的值域
* Node对象 是链表的指针域*/
int data;
Node Next;
/**
**************
* @param data
* 填充值域
**************
* */
public Node(int data){
Next=null;
this.data=data;
} // of Node
} //of class Node
/**
* 声明头结点 header
* */
Node header;
/**
**************
* 创建空链表
**************
* */
public day06_LinkList(){
header =new Node(0);
}// of day_06LinkList
/**
**************
* 重写toString方法
**************
* */
@Override
public String toString() {
String result="链表长度为:"+length+","+"链表元素有"+"";
if(length==0){
return "链表为空";
} // of if
Node tempNode=header.Next;
while (tempNode!=null){
result+=tempNode.data+",";
tempNode=tempNode.Next;
} //of while
return result;
} // of toString
/**
* reset方法重置链表*/
public void reset(){
length=0;
header.Next=null;
}
/**
*********************
* @param paraPosition
* 插入的位置
* @param paraValue
* 插入的值
********************
* */
public boolean insert(int paraPosition,int paraValue){
Node tempNode=header;
Node newNode;
if(length==0&¶Position!=0||paraPosition>length||paraPosition<0){
System.out.println("插入位置不合法,插入失败");
return false;
} //of if
newNode=new Node(paraValue);
for(int i=0;i<paraPosition;++i){
tempNode=tempNode.Next;
}// of for
newNode.Next=tempNode.Next;
tempNode.Next=newNode;
length++;
return true;
} // of insert
/**
*********************
* @param paraPosition
* 删除位置
********************
* */
public boolean delete(int paraPosition){
if(paraPosition<0||paraPosition>length-1){
System.out.println("删除位置不合法,删除失败");
return false;
} //of if
if(length==0){
System.out.println("链表为空");
return false;
} //of if
Node tempNode=header;
for(int i=0;i<paraPosition;++i){
tempNode=tempNode.Next;
} //of for i
tempNode.Next=tempNode.Next.Next;
length--;
return true;
} //of delete
/**
*********************
* @param paraValue
* 查找的元素的值
********************
* */
public int locate(int paraValue){
int tempPostion=-1,tempPositionV2=0;
Node tempNode=header.Next;
while(tempNode!=null){
if(tempNode.data==paraValue){
return tempPositionV2;
} // of if
tempNode=tempNode.Next;
tempPositionV2++;
} // of while
return tempPostion;
} // of locate
/**
* 程序入口
**************
* @param args
* 无参
**************
* */
public static void main(String args[]) {
day06_LinkList tempFirstList = new day06_LinkList();
System.out.println("初始化链表: " + tempFirstList.toString());
for (int i = 0; i < 8; i++) {
tempFirstList.insert(0, i);
} // Of for i
System.out.println("循环插入元素后: " + tempFirstList.toString());
System.out.println("查询元素的位置是"+tempFirstList.locate(5));
tempFirstList.insert(9, 9);
tempFirstList.delete(4);
tempFirstList.delete(2);
System.out.println("执行删除操作后: " + tempFirstList.toString());
tempFirstList.delete(0);
System.out.println("执行删除操作后: " + tempFirstList.toString());
for (int i = 0; i < 4; i++) {
tempFirstList.delete(0);
System.out.println("循环删除第: "+ i + "次后" +" "+ tempFirstList.toString());
} // Of for i
tempFirstList.reset();
System.out.println("重置链表后"+":"+tempFirstList);
} // Of main
} //of day06_LinkList
运行结果
总结:
内部类 Node是链表的节点,里面声明数据data与下一个节点Node,并利用构造方法给其赋值
单链表在存储结构上的实现要比顺序表难一些,但是我个人觉得这种 “链” 的思想很强大,感觉可以根据自己的需求通过 “链” 来创造一些前所未有的数据结构。
参考昨天顺序表,在今天的代码中也添加了 length 属性 ,用来记录单链表的长度,这样在判断插入、删除的位置时就不用去遍历整个链表,通过 length 属性可以直接判断,作为代价需要去维护这个属性。