线性表及其基本操作
线性表的定义:一个线性表(LinearList)是由n(n≥0)个数据元素(结点)所构成的有限序列。线性表逻辑地表示为:(a0,a1,…,an-1)。其中,n为线性表的长度,n=0时为空表。称i为ai在线性表中的位序号。
线性表的结构特点
a)它由n个同类型的元素组成;
b) 有且仅有一个第一个元素和最后一个元素;
c) 每个元素除第一个元素和最后一个元素之外,有且仅有一个前驱和一个后继。- 基本操作
a) Clear();
b) isEmpty();
c) length();
d) get(i);
e) insert(I,x);
f) remove(i);
g) indexOf(x);
h) display(); - 线性表抽象数据类型的Java接口描述
public interface IList(){
public void clear();
public BooleanisEmpty();
public int length();
public Object get(int i);
public void insert(int i,Object x);
public void remove(int i);
public int indexOf(Object x);
public void display();
}
线性表的顺序存储及其实现
- 顺序存储:用一组地址连续的存储单元 依次存放 线性表中的数据元素的存储结构。
2.顺序表的存储:
3.实现
public class SqList implements IList {
private Object[] listElem;
private int curLen;
//构造一个容量为maxSize的空顺序表函数
public SqList (int maxSize) {
curLen = 0;
listElem = new Object[maxSize];
}
// 顺序表置空函数
public void clear( ) {
curLen = 0;
}
// 判空函数
public boolean isEmpty( ) {
return curLen == 0;
}
//求线性表的数据元素并返回其值
public int length(){
return curLen;
}
//读取线性表第i个元素的值
public Object get(int i) throws Exception{
if(i<0||i>curLen-1)
throw new Exception("元素不存在");
return listElem[i];
}
//在线性表的第i位置插入值x
public void insert(int i,Object x) throws Exception{
//判断顺序表是否满
if(curLen==listElem.length)
throw new Exception("顺序表已经满");
if(i<0||i>curLen)
throw new Exception("插入位置不合法");
for(int j=curLen ;j>i;j--)
listElem[j]=listElem[j-1];
listElem[i]=x;
curLen++;
}
//删除指定位置的元素
public void remove(int i )throws Exception{
if(i<0||i>curLen)
throw new Exception("删除位置不合法");
for(int j = i;j<curLen-1;j++){
listElem[j]=listElem[j+1];
}
curLen--;
}
//顺序表的查找操作,返回相应的下标
public int index(Object x){
int j =0;
while(j<curLen&&listElem[j].equals(x){
j++;
}
if(j<curLen)
return j;
else
return -1;
}
//输出顺序表的数据元素
public void display(){
for(int j =0;j<curLen;j++){
system.out.print(listElem[i]+" ");
}
}
}
线性表的链式存储及其实现
单链表
- 单链表的表示
a. 用一组 地址任意的存储单元存放线性表中的数据元素。
b. 以元素 (数据元素的映象) + 指针 (指示后继元素存储位置)= 结点 (表示数据元素 或 数据元素的映象)
c. 以“结点的序列”表示线性表 称作链表
以线性表中第一个数据元素a0的存储地址作为线性表的地址,称作线性表的头指针。
有时为了操作方便,在第一个结点(首结点)之前虚加一个“头结点”,以指向头结点的指针为链表的头指针。
2.结点类的描述
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(){
head = new Node();//初始化头节点空
}
//构造一个长度为n的单链表
public LinkList(int n,boolean order ) throws Exception{
this();//初始化头结点
if(order)
create1(n);//尾插法建立单链表
else
create2(n);//头插法建立单链表
}
//尾插法建立单链表
public void create1(n) throws Exception{
Scanner sc = new Scanner(System.in);
for(int j =0;j<n;j++)
insert(length(),sc.next());
}
//头插法建立单链表
public void create2(n) throws Exception{
Scanner sc = new Scanner(System.in);
for(int j =0;j<n;j++)
insert(0,sc.next());//生成新结点,插入到表头
}
//按位序号查找
public Object get(int i ) throws Exception{
Node p = head.next;
int j =0;
while(p!=null&&j<i){
p=p.next;
j++;
}
if(j>i||p==null)
throw new Exception("元素部存在");
return p.data;
}
//按值查找
public int indexOf(Object x){
Node p = head.next;
int j =0;
while(p!=null&&!p.equals(x){
p=p.next;
j++;
}
if(p!=null)
return j;
else
return -1;
}
//带头结点的单链表插入
public void insert(int i,Object x) throws Exception{
Node p = head.next;
int j =-1;
while(p!=null&&j<i-1){//寻找第i个结点的前驱
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;
}
//不带头结点的插入操作
public void insert2(int i , Object x) throws Exception{
Node p = head;
int 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);
if(i==0){//插入位置为表头时
s.next = head;
head = s;
}
else{
s.next = p.next;
p.next = s;
}
}
//删除操作
public void remove(int i )throws Exception{
Node p = head.next;
int j =-1;
while(p!=null&&j<i-1){
p = p.next;
j++;
}
if(p==null||j>i-1)
throw new Exception("删除位置不合法");
p.next = p.next.next;
}
//置空
public void clear(){
head.data=null;
head.next=null;
}
//判断带头结点的单链表是否为空
public boolean isEmpty(){
return head.next == null;
}
//带头结点的单链表的长度
public int length(){
int length = 0;
Node p = head.next;
while(p!=null){
length++;
p=p.next;
}
return length;
}
//输出所有单链表的所有结点
public void diplay(){
Node p = head.next;
while(p!=null){
System.out.print(p.data+" ");
p=p.next;
}
System.out.print();
}
}
顺序存储与链式存储的比较
. | 顺序表 | 链表 |
---|---|---|
空间大小 | 相对稳定 | 可根据需要进行动态变化,较灵活 |
存储密度 | 较高(只存放数据元素值本身 | 较低(除存放数据元素值本身之外,还存放指针) |
创建 | 简单(利用数组) | 较复杂(头、尾插法) |
存储操作 | 简单(随机存取) | 较复杂(顺序存取) |
插入操作 | 不方便(会引起元素移动) | 方便(只要修改相关链) |
删除操作 | 不方便(会引起元素移动) | 方便(只要修改相关链) |