本篇用java实现数据结构的线性存储
作为我学java数据结构学习笔记
源码分享在github:数据结构,当然你也可以从下面的代码片中或我其他博文获取
这是第一部分线性存储,接下来我会陆续更新哒~
1.接口
package code.list;
public interface Ilist {
public void clear();//置空
public boolean isEmpty();//判空
public int length();
public Object get(int i) throws Exception;//返回线性表中第i个值
public void insert(int i,Object x) throws Exception;
public void remove(int i) throws Exception;
public void display();
}
2.顺序表
package code.list;
/*
* 顺序表
*
* */
public class SqList implements Ilist {
private Object []listElme; //线性表储存空间
private int curLen; //线性表当前长度
//顺序表类的构造函数,构造一个储存空间容量为maxSize的线性表
public SqList(int maxSize) {
curLen = 0; //设置顺序表当前长度为0
listElme = new Object[maxSize]; //为顺序表分配maxSize个春村单元
}
//将一个以及存在 的线性表重置为空表
@Override
public void clear() {
curLen = 0;
}
//判断线性表中的数据元素个数是否为0,若为0,则返回true;否则返回false
public boolean isEmpty() {
return curLen==0;
}
//求线性表中的数据元素个数并返回其值
public int length() {
return curLen;
}
//读取到线性表中的第i个数据元素并由函数返回其值,其中i的取值范围为:0<=i<=length()-1,若i值不在此范围则抛出异常
public Object get(int i) throws Exception{
if(i<0||i>curLen-1) //i小于0或者大一表长减一
throw new Exception("第"+i+"个元素不存在");//抛出异常
return listElme[i];//返回顺序表中第i个数据元素
}
//在线性表的第i个数据元素之前插入一个值为x的数据元素
public void insert(int i, Object x) throws Exception {
if(curLen==listElme.length)//判断顺序表是否已经满
throw new Exception("顺序表已满");//抛出异常
if(i<0||i>curLen)//i不合法
throw new Exception("插入位置不合法");//抛出异常
for(int j = curLen;j > i;j --){
listElme[j] = listElme[j-1];
}//插入位置及其以后的所有数据元素后移一位
listElme[i] = x;//插入x
curLen++;//表长加1
}
//删除并返回线性表中 第i个元素
public void remove(int i) throws Exception{
if(i<0||i>curLen-1){//i不合法
throw new Exception("删除位置不合法");//抛出异常
}
for(int j = i;j<curLen-1;j++){
listElme[j] = listElme[j+1];//被删除元素之后的所有数据左移一个存储位置
}
curLen--;//表长减一
}
//返回线性表中首次出现制定的数据元素的位序号,若线性表中不包含次数据元素,则返回-1
public int indexOf(Object x) {
int j = 0;//j指示顺序表中待比较的数据元素,起初值指示顺序表中第0个元素
while(j<curLen&&!listElme[j].equals(x))//依次比较,如果j<curLen并且此项不等于x
j++;
if(j<curLen)//判断j的位置是否位于顺序表中
return j;
else {
return -1;//值为x的数据元素再顺序表中不存在
}
}
//输出线性表中的数据元素
public void display() {
for(int j = 0;j<curLen;j++)
System.out.print(listElme[j]+"");
System.out.println();
}
}
3.链表
链表节点类
package code.list;
public class Node {
public Object data;//存放节点值
public Node next;//后继节点的引用
//无参数时的构造函数
public Node(){
this(null,null);
}
//带一个参数时的构造函数
public Node(Object data){
this(data,null);
}
//带两个参数的构造函数
public Node(Object data, Node next){
this.data = data;
this.next = next;
}
}
链表实现:
package code.list;
/*
* 链表
*
* */
import java.util.Scanner;
public class LinkList implements Ilist {
public Node head;//单链表的头指针
//单链表的构造函数
public LinkList(){
head = new Node();//初始化头节点
}
//构造一个长度为n的单链表
public LinkList(int n,boolean Order) throws Exception{
this();//初始化头节点
if(Order){//用尾插法顺序建立单链表
create1(n);
}else {//用头插法逆序建立单链表
create2(n);
}
}
//用尾插法顺序建立单链表,其中n为单链表的结点个数
public void create1(int n) throws Exception{
Scanner sc = new Scanner(System.in);//构造用于输入的对象
for(int j = 0;j<n;j++){//输入n个结点的数据域值
insert(length(), sc.next());//生成新结点,插入到表尾
}
}
//用头插法逆序建立单链表,其中n为单链表的节点个数
public void create2(int n) throws Exception{
Scanner sc = new Scanner(System.in);//构造用于输入的对象
for(int j = 0;j<n;j++){//输入n个结点的数据域值
insert(0, sc.next());//生成新结点,插入到表尾
}
}
//将一个以及存在 的带头节点单链表重置为空表
public void clear() {
head.data = null;
head.next = null;
}
//判断带头节点的单链表是否为空
public boolean isEmpty() {
return head.next ==null;//头结点后面是首节点
}
//求带头节点的单链表的长度
public int length() {
Node p = head.next;//初始化,p指向首节点,length为计数器
int length = 0;
while(p!=null){//从首节点开始向后查找,直到p为空
p = p.next;//指向后继节点
++length;//长度增1
}
return length;
}
//读取到带头节点的单链表中的第i个节点(这里的第i个指的是从0开始计数)
public Object get(int i) throws Exception {
Node p = head.next;//初始化,p指向首节点,j为计数器
int j = 0;
while(p!=null&&j<i){//从首节点开始向后查找,直到p指向第i个结点或p为空
p = p.next;//指向后继结点
++j;//计数器的值增1
}
if(j > i||p==null){
throw new Exception("第"+i+"个元素不存在");
}
return p.data;
}
//在第i个节点前插入一个值为x的新节点
public void insert(int i, Object x) throws Exception {
Node p = head;//初始化p为头节点,j为计数器
int j = -1;
while(p!=null&&j<i-1){//寻找第i个结点的前驱
p = p.next;
++j;
}
if(j>i-1||p==null){ //第一个条件若为真,则说明参数i的值小于0,若第二个条件为真,则说明参数i的值大于表长
throw new Exception("插入位置不合法");
}
Node s = new Node(x);//生成新结点
s.next = p.next;//修改连,使新结点插入单链表中
p.next = s;
}
//删除第i个节点
public void remove(int i) throws Exception {
Node p = head;//初始化p指向头节点,j为计数器
int j = -1;
while(p.next!=null&&j<i-1){//寻找第i个结点的前驱
p = p.next;
++j;
}
if(j>i-1||p.next == null){
throw new Exception("删除位置不合法");
}
p.next = p.next.next;//修改链指针,使待删除结点从单链表中从单链表中脱离出来
}
//查找值为x的节点
public int indexOf(Object x) {
Node p = head.next;//初始化,p指向首结点,j为计数器
int j = 0;//下面从单链表中 的首结点你开始查找,直到p.data为x或到达单链表的表尾
while(p!=null&&!p.data.equals(x)){
p = p.next;//指向下一个结点
++j;
}
if(p!=null){
return j;
}else{
return -1;
}
}
//输出所有节点
public void display() {
Node node = head.next;//取出带头节点的单链表中的首节点
while(node!=null){
System.out.print(node.data +" ");//输出节点的值
node = node.next;//取下一个节点
}
System.out.println();//换行
}
}
4.双循环链表
双循环链表节点类
package code.list;
/*
* 双向链表的节点类
* */
public class DuLNode {
public Object data; //数据域
public DuLNode prior; //存放指向前驱结点的指针域
public DuLNode next; //存放指向后继结点的指针域
public DuLNode(){ }
public DuLNode(Object data){
this.data = data;
this.prior = null;
this.next = null;
}
}
双循环链表实现类:
package code.list;
import java.util.Scanner;
/*
* 双向循环链表
*
* */
public class DuLinkList implements Ilist{
public DuLNode head; //双向循环链表的头结点
//双向循环链表的构造函数,构造只含有一个头节点的双向循环链表
public DuLinkList(){
head = new DuLNode();
head.prior = head;
head.next = head;
}
//从表尾到表头逆向创建双向循环链表的算法,其中n为该双向循环链表的节点个数
public DuLinkList(int n) throws Exception{
this();
Scanner sc = new Scanner(System.in);
for (int j = 0;j < n;j++ ){
insert(0,sc.next());//生成新的节点插入到表头
}
}
@Override
public void clear() {
this.head.next = null;
this.head.prior = null;
this.head.data = null;
}
@Override
public boolean isEmpty() {
return head.next ==null && head.prior == null;
}
@Override
public int length() {
DuLNode p = head.next;
int length = 0;
while (p != head){
p = p.next;
length++;
}
return length;
}
@Override
public Object get(int i) throws Exception {
DuLNode p = head.next;//初始化,p指向首节点,j为计数器
int j = 0;
while(p!=head&&j<i){//从首节点开始向后查找,直到p指向第i个结点或p为head
p = p.next;//指向后继结点
++j;//计数器的值增1
}
if(j > i||p==head){
throw new Exception("第"+i+"个元素不存在");
}
return p.data;
}
//在带头节点的双向循环链表中的插入操作
@Override
public void insert(int i, Object x) throws Exception {
DuLNode p = head.next;
int j = 0;
while (!p.equals(head) && j < i){//寻找到插入位置i
p = p.next;
++j;
}
if (j != i && !p.equals(head)) //i不合法
throw new Exception("插入位置不合法");
DuLNode s = new DuLNode(x);//生成新节点s
p.prior.next = s;
s.prior = p.prior;
s.next = p;
p.prior = s;
}
//带头结点的双向循环链表中的删除操作
@Override
public void remove(int i) throws Exception {
DuLNode p = head.next;
int j = 0;
while (!p.equals(head) && j <i){
p = p.next;
++j;
}
if (j != i){
throw new Exception("删除位置不合理");
}
p.prior.next = p.next;
p.next.prior = p.prior;
}
@Override
public void display() {
DuLNode node = head.next;
while (!node.equals((head))){
System.out.println(node.data+" ");
node = node.next;
}
System.out.println();
}
}