一、绪论
二、算法
三、线性表
四、栈和队列
五、串
六、树
七、图
八、查找
九、排序
三、线性表
线性表定义:另个或多个数据元素的有限序列(除第一个无前驱和最后一个无后续)(有限、有序)。
表长:线性表元素个数定义为表的长度,n=0时称为空表。
复杂情况下一个数据元素可以有多个数据项组成。
线性表的基本操作:
import java.util.ArrayList;
import java.util.List;
public class Linner {
// 构造一个空的线性表
public List create(){
return new ArrayList();
}
// 初始化线性表
private void init(int length,List list) {
for(int i=1;i<=length;i++){
list.add(i);
}
}
// 销毁线性表
private void destroy(List list){
list = null;
}
// 清空线性表
private void clear(List list){
list.clear();
}
// 判定线性表是否为空
private boolean isEmpty(List list){
return list.isEmpty();
}
// 表长度
private int length(List list){
return list.size();
}
// 获取第i个数据元素的值
private int getNum(int getNum,List list) {
for (int i=0;i list) {
for (int i=0;i list){
return list.get(indexNum-1);
}
// 非最后一个元素,返回后继
private int getNext(int indexNum,List list){
return list.get(indexNum+1);
}
// 列举线性表的所有元素
private void dump(List list) {
for(int i=0;i list= l.create();
l.init(10, list);
}
}
线性表的顺序存储结构:指用一连续地址存储单元一次存储线性变的元素,对于获取对应位置元素很方便。存取时间性能O(1)。而在插入与删除时的时间复杂度是O(n)。线性表适合数据元素不多,而操作多是存取的应用。
线性表的优缺点:无需为表的逻辑结构增加额外的存储空间,可以快速的存取表中的任何一位置的元素,缺点:插入和删除移动大量的元素,当线性表长度变化较大时难以确定存储空间的容量,造成存储空间的碎片。
线性表的链式存储:线性表只需要存储元素,在链式存储中不仅要存储元素还要存储后继元素的存储地址。(数据域与指针域组合成结点)。n个结点组合成链表。链表第一个结点的存储位置为头指针。
头结点与头指针:头指针是指链表指向第一个结点的指针,如链表有头结点则指向头结点,无论链表是否为空,头指针均不为空,头指针是链表的必要元素。头结点:是为了操作统一和方便设立的放在第一个元素前面,其数据域一般无意义,有了头结点对第一个元素的节点前的插入和删除操作就统一了。头结点不一定是链表必要。
链表的操作
public class Listlink {
public class Node {
protected Node next; //指针域
protected int data;//数据域
public Node( int data) {
this. data = data;
}
//显示此结点
public void display() {
System. out.print( data + " ");
}
}
public class LinkList {
public Node first; // 定义一个头结点
private int pos = 0;// 结点的位置
public LinkList() {
this. first = null;
}
// 插入一个头节点
public void addFirstNode( int data) {
Node node = new Node(data);
node. next = first;
first = node;
}
// 删除一个头结点,并返回头结点
public Node deleteFirstNode() {
Node tempNode = first;
first = tempNode. next;
return tempNode;
}
// 在任意位置插入节点 在index的后面插入
public void add(int index, int data) {
Node node = new Node(data);
Node current = first;
Node previous = first;
while ( pos != index) {
previous = current;
current = current. next;
pos++;
}
node. next = current;
previous. next = node;
pos = 0;
}
// 删除任意位置的节点
public Node deletePos( int index) {
Node current = first;
Node previous = first;
while ( pos != index) {
pos++;
previous = current;
current = current. next;
}
if(current == first) {
first = first. next;
} else {
pos = 0;
previous. next = current. next;
}
return current;
}
// 根据节点的data删除节点(仅仅删除第一个)
public Node deleteData( int data) {
Node current = first;
Node previous = first; //记住上一个节点
while (current. data != data) {
if (current. next == null) {
return null;
}
previous = current;
current = current. next;
}
if(current == first) {
first = first. next;
} else {
previous. next = current. next;
}
return current;
}
// 显示出所有的节点信息
public void displayNodes() {
Node current = first;
while (current != null) {
current.display();
current = current. next;
}
System. out.println();
}
// 根据位置查找结点信息
public Node findPos( int index) {
Node current = first;
if ( pos != index) {
current = current. next;
pos++;
}
return current;
}
// 根据数据查找结点
public Node findData( int data) {
Node current = first;
while (current. data != data) {
if (current. next == null)
return null;
current = current. next;
}
return current;
}
}
public static void main(String[] args) {
}
}
单链表的优缺点:存取物理位置随意不需要连续的单元,查找时间复杂度O(n),插入与删除O(1),空间性能顺序表需要预先分配存储空间,链表不需要。
静态链表:用数组描述的链表叫静态链表,这里的数组元素包含两个数据域(data和cur)cur相当于链表的next指针叫游标。静态链表的优缺点:在插入和删除操作时只需要移动游标,不需要移动元素,缺点是没有解决存储分配带来的表长难以确定的问题,失去顺序存储结构随机存储的特性。
循环链表:将单链表的终端结点的指针由空改为指向头结点,就是整个单链表形成一个环形成单链表。循环链表的操作与单链表基本一致,差别在于算法中的循环条件不是p或者p->next是否为空, 而是他们是否等于头指针。
class rcode{
private Object data; //定义数据域
private rcode nextreode; //定义下一个节点
private rcode head=null;//定义头节点
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public rcode getNextreode() {
return nextreode;
}
public void setNextreode(rcode next) {
this.nextreode = next;
}
public void initCycleList(Object data){ //循环链表的初始化
head=new rcode();
head.setData(data);
head.setNextreode(head);
}
public void insertCycleListTail(Object data){
rcode inCNode=new rcode();
inCNode.setData(data);
if (head==head.getNextreode()) { //如果原链表只有一个节点,直接插入
head.setNextreode(inCNode);
inCNode.setNextreode(head);
}else { //原链表不止一个节点
rcode temp=head; //创建临时节点
while (head!=temp.getNextreode()) { //遍历循环链表,找到最后一个节点
temp=temp.getNextreode();
}
temp.setNextreode(inCNode); //插入节点
inCNode.setNextreode(head);
}
}
//求循环链表的长度
public int cycleListSize(){
rcode temp=head;
int size=0;
while (temp.getNextreode()!=head) {
size++;
temp=temp.getNextreode();
}
return size;
}
//判断循环链表中是否存在某个元素
public Boolean isContain(Object data){
rcode temp=head;
while (temp.getNextreode()!=head) {
if (temp.getData().equals(data)) {
return true;
}
temp=temp.getNextreode();
}
return false;
}
//获取循环链表中第i个位置的元素
public rcode getCNode(int i){
if (i<0||i>cycleListSize()) {
System.out.println("输入有误");
return null;
}else {
int count=0;
rcode temp=head;
rcode retCNode=new rcode();
while (head!=temp.getNextreode()) {
if (count==i) {
retCNode.setData(temp.getData());
break;
}
temp=temp.getNextreode();
count++;
}
return retCNode;
}
}
//打印循环链表
public void printCycleList(){
rcode temp=head;
while (head!=temp.getNextreode()) {
System.out.print(temp.getData()+" ");
temp=temp.getNextreode();
}
System.out.println();
}
}
public class reviList {
public static void main(String[] args) {
}
}
双向链表:在双向链表的结点中有两个指针域, 其一指向直接后继,另一指向直接前驱。