版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LiuXudongHnu/article/details/68066227
线性表是一种基本的数据结构,线性表在计算机中可以用顺序存储和链式存储两种存储结构来表示。其中,用顺序存储结构表示的线性表称为顺序表,用链式存储结构表示的称为链表。其中,链表又分为单链表、双向链表、循环链表。线性表结构简单,其长度可以动态的增长或减少、可以对线性表中任何数据元素进行访问、数据元素的插入和删除操作可以在线性表中的任何位置进行、求线性表中指定元素的前驱和后继。因此我们可以构造一个接口来:
public interface Ilist {
public void clear(); //将一各已经线性表置为空表
public boolean isEmpty(); //判断现行表是否为空,若为空,返回true
public int length(); //返回线性表中数据元素的个数,并返回其值
public Object get(int i) throws Exception; //读取并返回线性表中的第i个数据元素的值。
public void insert(int i,Object x) throws Exception; //在线性表的第i个元素之前插入一个值为x的数据元素。
public void remove(int i) throws Exception; //删除并返回线性表中第i个数据元素。
public int indexOf(Object x);//返回线性表中首次出现指定数据元素的位序号,如不包含,返回-1
public void display(); //返回线性表中各个数据元素的值。
}
1、顺序表:顺序存储的线性表。顺序存储是用一组地址连续的存储单元依次存放线性表中各个数据元素的存储结构。
public class SqList implements Ilist{
private Object[] listItem; //线性表的存储空间
private int curLen; //线性表的当前长度
public SqList(int maxSize) {
// TODO Auto-generated constructor stub
curLen=0; //置顺序表当前长度位0
listItem=new Object[maxSize]; //为顺序表分配maxSize个存储单元
}
@Override
public void clear() {
// TODO Auto-generated method stub
curLen=0;
}
@Override
public boolean isEmpty() { //判断链表是否为空
// TODO Auto-generated method stub
return curLen==0;
}
@Override
public int length() {
// TODO Auto-generated method stub
return curLen;
}
@Override
public Object get(int i) throws Exception {
// TODO Auto-generated method stub
if(i<0||i>curLen-1)
throw new Exception("第"+i+"个元素不存在");
return listItem[i];
}
@Override
public void insert(int i, Object x) throws Exception { //在线性表的第i个元素之前插入一个值为x的数据元素
// TODO Auto-generated method stub
if(i<0||i>curLen)
throw new Exception("插入位置不合法~!");
for(int j=curLen;j>i;j--){
listItem[j]=listItem[j-1];
}
listItem[i]=x;
curLen++;
}
@Override
public void remove(int i) throws Exception { //删除并返回线性表中第i个数据元素
// TODO Auto-generated method stub
if(i<0||i>curLen)
throw new Exception("删除位置不合法~!");
for(int j=i;j<curLen-1;j++){ //被删除元素之后的所有数据元素左移一个位置
listItem[j]=listItem[j+1];
}
curLen--;
}
@Override
public int indexOf(Object x) { //返回线性表中首次出现指定数据元素的位序号,如不包含,返回-1
// TODO Auto-generated method stub
int j=0;
while(j<curLen&&!listItem[j].equals(x)){
j++;
}
if(j<curLen)
return j;
else
return -1;
}
@Override
public void display() {
// TODO Auto-generated method stub
for(int j=0;j<curLen;j++){
System.out.print(listItem[j]+" ");
}
System.out.println();
}
}
2、单链表:采用链式存储方式存储的线性表称为链表,而链表中每个结点包含存放数据元素值的数据域和存放指向逻辑上相邻结点的指针域。链表是由结点组成的,而结点是由你自己定义的,结点有两个部分,一个数据部分,一个是指针部分(JAVA中没有指针,为了形象采用这个说法。)。单链表是一个结点中只包含一个指针域。单链表是通过指向后继结点的指针把一串结点链接成一个链。以线性表中第一个数据元素的存储地址作为线性表的起始地址,称作线性表的头指针。一个单链表就是由它的头指针head来唯一的标示它。单链表的最后一个结点没有后继,所以其指针域的值为空。实现代码:
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;
}
}
public class LinkList implements Ilist{
public Node head; //头指针
public LinkList() { //单链表的构造函数
// TODO Auto-generated constructor stub
head=new Node(); //初始化头结点
}
public LinkList(int n,boolean order) throws Exception{ //构造一个长度为n的单链表
this(); //初始化头结点
if(order) //用头插法顺序建立单链表
create1(n);
else //用尾插法逆位序建立单链表
create2(n);
}
private void create1(int n) throws Exception { //用头插法顺序建立单链表
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
for(int j=0;j<n;j++){
insert(length(), sc.next());
}
}
private void create2(int n) throws Exception { //用尾插法逆位序建立单链表
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
for(int j=0;j<n;j++){
insert(0, sc.next());
}
}
@Override
public void clear() { //置为空表
// TODO Auto-generated method stub
head.data=null;
head.next=null;
}
@Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return head.next==null;
}
@Override
public int length() { //求带头结点的单链表的长度
// TODO Auto-generated method stub
Node pNode=head.next;
int length=0;
while(pNode!=null){
pNode=pNode.next;
length++;
}
return length;
}
@Override
public Object get(int i) throws Exception { //读取带头结点的单链表中的第i个结点
// TODO Auto-generated method stub
Node p=head.next;
int j=0;
while(p!=null&&j<i){
p=p.next;
j++;
}
if(j>i||p==null){
throw new Exception("第"+i+"个元素不存在~!");
}
return p.data;
}
@Override
public void insert(int i, Object x) throws Exception { //带头结点的插入
// TODO Auto-generated method stub
Node p=head;
int j=-1; //若不带头结点,可将j设为0
while(p!=null&&j<i-1){
p=p.next;
j++;
}
if(j>i-1||p==null){
throw new Exception("插入位置不合法");
}
Node s=new Node(x); //构造一个新结点
s.next=p.next;
p.next=s;
}
@Override
public void remove(int i) throws Exception {
// TODO Auto-generated method stub
Node pNode=head;
int j=-1;
while(pNode.next!=null&&j<i-1){
pNode=pNode.next;
j++;
}
if(j>i-1||pNode.next==null)
throw new Exception("删除位置不合法");
pNode.next=pNode.next.next;
}
@Override
public int indexOf(Object x) { //在带头结点的单链表中查找置为x的结点
// TODO Auto-generated method stub
Node pNode=head.next;
int j=0;
while(pNode!=null&&!pNode.data.equals(x)){
pNode=pNode.next;
++j;
}
if(pNode!=null){
return j;
}
else
return -1;
}
@Override
public void display() { //输出链表中的所有结点
// TODO Auto-generated method stub
Node node=head.next;
while(node!=null){
System.out.print(node.data+" ");
}
System.out.println();
}
}
3、双向循环链表:循环链表:其结构与单链表相似,只是单链表的首尾相连,即最后一个结点的后继指向第一个结点。双向链表:两个指针域,一个指向前驱,一个指向后继。这里为了方便,直接给出一个双向循环链表的代码。
扫描二维码关注公众号,回复:
3835652 查看本文章
public class DulNode {
public Object data; //数据域
public DulNode prior; //前驱指针域
public DulNode next; //后继指针域
public DulNode(){ //无参构造函数
this(null);
}
public DulNode(Object data){ //用于构造数据域值为data的结点
this.data=data;
this.prior=null;
this.next=null;
}
}
import java.util.Scanner;
public class DulLinkList implements Ilist{
public DulNode head; //用于构造头结点
public DulLinkList() { //双向循环链表的构造函数,用于构造只有一个头结点的双向循环链表
// TODO Auto-generated constructor stub
head=new DulNode();
head.prior=head;
head.next=head;
}
public DulLinkList(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() { //清空链表
// TODO Auto-generated method stub
head.prior=head;
head.next=head;
}
@Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return head.next.equals(head);
}
@Override
public int length() {
// TODO Auto-generated method stub
int j=0;
while(!head.next.equals(head)){
head=head.next;
j++;
}
return j;
}
@Override
public Object get(int i) throws Exception {
// TODO Auto-generated method stub
DulNode p=new DulNode();
int j=0;
while(j<i&&!p.equals(head)){
p=p.next;
j++;
}
if(j<i){
throw new Exception("查找位置不合法~!");
}
return p.data;
}
@Override
public void insert(int i, Object x) throws Exception { //在带头结点的双向循环链表中的插入操作
// TODO Auto-generated method stub
DulNode p=head.next;
int j=0;
while(!p.equals(head)&&j<i){
p=p.next;
j++;
}
if(j!=i&&!p.equals(head))
throw new Exception("插入位置不合法");
DulNode dl=new DulNode(x);
p.prior.next=dl;
dl.prior=p.prior;
dl.next=p;
p.prior=dl;
}
@Override
public void remove(int i) throws Exception {
// TODO Auto-generated method stub
DulNode dul=head.next;
int j=0;
while(!dul.equals(head)&&j<i){
dul=dul.next;
j++;
}
if(j!=i){
throw new Exception("删除位置不合法");
}
dul.prior.next=dul.next;
dul.next.prior=dul.prior;
}
@Override
public int indexOf(Object x) {
// TODO Auto-generated method stub
DulNode p=head.next;
int j=0;
while(p.next!=head&&!p.data.equals(x)){
p=p.next;
j++;
}
return j;
}
@Override
public void display() {
// TODO Auto-generated method stub
DulNode node=head.next;
while(!node.equals(head)){
System.out.print(node.data+" ");
node=node.next;
}
System.out.println();
}
}