1、基本概念
形如A0,A1,A2…AN-1成为一般表,如果表的大小为0成为空表
对于空表以外的任何表,Ai-1为Ai的前驱,Ai+1为Ai的后驱,A0没有前驱,AN-1没有后驱
线性表分为顺序表和链表
2、顺序表
顺序表的物理内存是连续的。在存、读取数据时,不管是在哪个位置,时间复杂度都是O(1)。而在插入或者删除时,时间复杂度都是O(n)。比较适合存取数据,不适合经常插入和删除数据的应用。
- 优点:
- 无需为了表示表中元素之间的逻辑关系而增加额外的存储空间(相对于链式存储而言)。
- 可以快速的存取表中任意位置的元素。
- 缺点:
- 插入和删除操作需要移动大量的元素。
- 当线性表长度变化较大时,难以确定存储空间的容量。
- 容易造成存储空间的“碎片”(因为线性表的顺序存储结构申请的内存空间都以连续的,如果因为某些操作(比如删除操作)导致某个部分出现了一小块的不连续内存空间,因为这一小块内存空间太小不能够再次被利用/分配,那么就造成了内存浪费,也就是“碎片”)
3、链表
3.1 链表种类
单链表、静态链表、循环链表、双向链表
主要操作:创建、插入、删除、反转等
3.2 单链表的基本操作
public class LinkList {
class Node{
int data;
Node next;
public Node(int data){
this.data = data;
}
}
public Node first;
public int len;
public LinkList(){
this.first = null;
this.len = 0;
}
//添加到结尾
public void addTail(int data){
Node node = new Node(data);
if (this.first == null)
this.first = node;
else {
Node index = this.first;
while (index.next != null)
index = index.next;
index.next = node;
}
this.len++;
}
//在指定位置添加数据
public int addIndex(int index, int data){
if(index>this.len || index<0)
return -1;
Node node = new Node(data);
if(index == 0){ //插入开头
node.next = this.first;
this.first = node;
return 0;
}
Node tmpNode=null, curNode = this.first;
int pos = 0;
while(pos != index){
tmpNode = curNode;
curNode = curNode.next;
pos++;
}
tmpNode.next = node;
node.next = curNode;
this.len++;
return 0;
}
//删除指定位置的数据
public int delIndex(int index){
if(index>=this.len || index<0)
return -1;
if(index == 0){
this.first = this.first.next;
return 0;
}
Node tmpNode=null, curNode=this.first;
int pos = 0;
while(pos != index){
tmpNode = curNode;
curNode = curNode.next;
pos++;
}
tmpNode.next = curNode.next;
this.len--;
return 0;
}
//打印数据
public void print(){
if (this.first != null){
Node index = this.first;
while (index != null) {
System.out.print("\t" + index.data);
index = index.next;
}
}
}
//翻转链表 for循环
public void reverWithFor(){
if(this.len <= 1)
return;
Node preNode = null;
Node curNode = this.first;
Node nextNode = null;
while(curNode != null) {
nextNode = curNode.next;
curNode.next = preNode;
preNode = curNode;
curNode = nextNode;
}
this.first = preNode;
}
//翻转链表 递归
public Node reverWithRecursion(Node node){
if(node==null||node.next ==null)
return node;
Node prev = reverWithRecursion(node.next);
node.next.next = node;
node.next = null;
return prev;
}
}
调用:
public static void main(String[] args) {
LinkList ll = new LinkList();
ll.addTail(1);
ll.addTail(2);
ll.addTail(3);
ll.addTail(4);
ll.addTail(5);
ll.print();
System.out.println();
ll.addIndex(1, 6);
ll.print();
System.out.println();
ll.delIndex(1);
ll.print();
System.out.println();
ll.reverWithFor();
ll.print();
System.out.println();
ll.first = ll.reverWithRecursion(ll.first);
ll.print();
}
3.3 静态链表
静态链表就是将数据以数组的形式组建
3.4 双向链表
class Node{
int data;
Node next;
Node pre; //指向前一个数据
public Node(int data){
this.data = data;
}
}