Java内存中,栈内存和堆内存占了很大一部分空间:栈内存的存储是顺序结构,堆内存的存储是离散结构。
顺序表
![d3384f05-39d1-46d9-a580-bf4b531d740c](https://images2015.cnblogs.com/blog/947400/201605/947400-20160526231417069-430130542.png)
类成员
int maxSize; //最大长度
int size; //当前长度
Object[] listArray; //对象数组
类主要方法
删除
移动元素时,要从前往后操作。
publicvoiddelete(int index) throws Exception
{
//容错性
if(isEmpty()){
thrownewException("顺序表为空,无法删除!");
}
if(index <0|| index > size -1){
thrownewException("参数错误!");
}
//移动元素(从前往后操作)
for(int j = index; j < size -1; j++)
listArray[j]= listArray[j +1];
listArray[size -1]= null; //注意释放内存(避免内存泄漏)
size--;
}
插入
移动元素时,要从后往前操作,不能从前往后操作,不然元素会被覆盖的。
publicvoid insert(int index,Object obj) throws Exception
{
//容错性
if(size == maxSize){
thrownewException("顺序表已满,无法插入!");
}
if(index <0|| index > size){
thrownewException("参数错误!");
}
//移动元素(从后往前操作)
for(int j = size -1; j >= index; j--)
listArray[j +1]= listArray[j];
listArray[index]= obj;
size++;
单向链表
- 带头结点:(操作统一,推荐)
![](https://images2015.cnblogs.com/blog/947400/201605/947400-20160526231417647-1127791268.png)
![](https://images2015.cnblogs.com/blog/947400/201605/947400-20160526231418256-219915269.jpg)
- 不带头结点:
![](https://images2015.cnblogs.com/blog/947400/201605/947400-20160526231418756-1621087703.jpg)
类成员
//结点类
publicclassNode{
publicObject data;
publicNode next;
publicNode(Object obj,Node next){
this.data = obj;
this.next = next;
}
}
Node head; //记录头结点信息即可(头结点下标为-1)
int size;
类主要方法
定位
//定位
publicNode locate(int index) throws Exception
{
//容错性
if(index <-1|| index > size)
thrownewException("参数错误!");
//定位到temp指向第index个(index为下标)
Node temp = head;
for(int i =-1; i < index; i++)
if(temp != null)
temp = temp.next;
return temp;
}
删除
![](https://images2015.cnblogs.com/blog/947400/201605/947400-20160526231419413-1987517855.png)
publicvoiddelete(int index) throws Exception
{
//容错性
if(isEmpty())
thrownewException("链表为空,无法删除!");
if(index <0|| index > size -1)
thrownewException("参数错误!");
Node temp = locate(index -1); //定位到要操作结点的前一个结点对象
temp.next = temp.next.next;
size--;
}
插入
![](https://images2015.cnblogs.com/blog/947400/201605/947400-20160526231420069-1886988907.png)
publicvoid insert(int index,Object obj) throws Exception
{
//容错性
if(index <0|| index > size )
thrownewException("参数错误!");
Node temp = locate(index -1); //定位到要操作结点的前一个结点对象
Node p =newNode(obj,temp.next);
temp.next = p;
size++;
}
双向链表
![](https://images2015.cnblogs.com/blog/947400/201605/947400-20160526231420741-400522714.png)
类成员
//结点类
publicclassNode{
publicObject data;
publicNode next;
publicNode prior;
publicNode(Object obj,Node next,Node prior){
this.data = obj;
this.next = next;
this.prior = prior;
}
}
Node head; //记录头结点信息即可(头结点下标为-1)
int size;
类主要方法
定位
//定位
publicNode locate(int index) throws Exception
{
//容错性
if(index <-1|| index > size)
thrownewException("参数错误!");
//定位到temp指向第index个(index为下标,从0开始)
Node temp = head;
for(int i =-1; i < index; i++)
if(temp != null)
temp = temp.next;
return temp;
}
删除
![](https://images2015.cnblogs.com/blog/947400/201605/947400-20160526231421397-1899259753.jpg)
publicvoiddelete(int index) throws Exception{
if(isEmpty())
thrownewException("链表为空,无法删除!");
if(index <0|| index > size -1)
thrownewException("参数错误!");
Node temp = locate(index -1); //定位到要操作结点的前一个结点对象
temp.next = temp.next.next;
if(temp.next != null) //当删除到最后一个元素:temp.next == null
temp.next.prior = temp;
size--;
}
插入
![](https://images2015.cnblogs.com/blog/947400/201605/947400-20160526231421819-1296520930.jpg)
publicvoid insert(int index,Object obj) throws Exception{
//容错性
if(index <0|| index > size )
thrownewException("参数错误!");
Node temp = locate(index -1); //定位到要操作结点的前一个结点对象
Node p =newNode(obj,temp.next,temp);
temp.next = p;
if(p.next != null) //当插入到最后一个位置:p.next == null
p.next.prior = p;
size++;
}
循环单向链表
空:
![](https://images2015.cnblogs.com/blog/947400/201605/947400-20160526231422397-2078720323.jpg)
非空:
![](https://images2015.cnblogs.com/blog/947400/201605/947400-20160526231423069-862880588.jpg)
循环双向链表
![](https://images2015.cnblogs.com/blog/947400/201605/947400-20160526231423600-2017002932.png)
静态链表
![](https://images2015.cnblogs.com/blog/947400/201605/947400-20160526231424256-447945404.jpg)
顺序表与链表比较
顺序表:
- 优点:
支持随机读取O(1)
- 缺点:
- 插入删除操作平均移动大约表中一半的元素,对n较大的顺序表效率低。(移动元素涉及内存的写入,消耗较大)
- 需要预先分配足够大的存储空间:估计过大,可能会导致顺序表后部大量闲置;预先分配过小,又会造成溢出。
链表:
优点:
- 不需要预先给出数据元素的最大个数
- 插入和删除操作时不需要移动数据元素
缺点:
不支持随机读取,单链表取数据元素操作的时间复杂度为O(n)