线性表
顺序表
接口
/**
* 线性表抽象数据类型的Java接口描述
*/
public interface IList {
// 将一个已经存在的线性表置成空表
void clear();
// 判断当前线性表中的数据元素个数是否为0,若为0则函数返回true,否则返回false
boolean isEmpty();
// 求线性表中的数据元素个数并由函数返回其值
int length();
// 读取到线性表中的第i个数据元素并由函数返回其值。其中i取值范围为:0≤i≤length()-1,如果i值不在此范围则抛出异常
Object get(int i) throws Exception;
//在线性表的第i个数据元素之前插入一个值为x的数据元素。其中i取值范围为:0≤i≤length()。如果i值不在此范围则抛出异常,当i=0时表示在表头插入一个数据元素x,当i=length()时表示在表尾插入一个数据元素x
void insert(int i, Object x) throws Exception;
// 将线性表中第i个数据元素删除。其中i取值范围为:0≤i≤length()- 1,如果i值不在此范围则抛出异常
void remove(int i) throws Exception;
// 返回线性表中首次出现指定元素的索引,如果列表不包含此元素,则返回 -1
int indexOf(Object x);
// 输出线性表中的数据元素
void display();
}
实现类
/**
* 顺序表接口的描述
*/
public class SqList implements IList {
private Object[] listElem;//线性表存储空间
private int curLen;//当前长度
//顺序表的构造函数,构造一个存储空间容量为maxSize的线性表
public SqList(int maxSize){
curLen=0;//置顺序表的当前长度为0
listElem=new Object[maxSize];//为顺序表分配maxSize个存储单元
}
//将一个已经存在的线性表置成空表
@Override
public void clear() {
curLen=0;//置顺序表的当前长度为0
}
//判断当前线性表中数据元素个数是否为0,若为0则函数返回true,否则返回false
@Override
public boolean isEmpty() {
return curLen==0;
}
//求线性表中的数据元素个数并由函数返回其值
@Override
public int length() {
return curLen;
}
//读取到线性表中的第i个数据元素并由函数返回其值。其中i取值范围为:0≤i≤length()-1,如果i值不在此范围则抛出异常
@Override
public Object get(int i) throws Exception {
if (i<0 || i>curLen-1)
throw new Exception("第" + i + "个元素不存在");
return listElem[i];
}
//在线性表的第i个数据元素之前插入一个值为x的数据元素。其中i取值范围为:0≤i≤length()。如果i值不在此范围则抛出异常,
//当i=0时表示在表头插入一个数据元素x,当i=length()时表示在表尾插入一个数据元素x
@Override
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; //插入x
curLen++;//表长度增1
}
//将线性表中第i个数据元素删除。其中i取值范围为:0≤i≤length()- 1,如果i值不在此范围则抛出异常
@Override
public void remove(int i) throws Exception {
if (i<0 || i>curLen-1)
throw new Exception("删除位置不合理");
for (int j=i;j<curLen-1;j++)
listElem[j]=listElem[j+1];//被删除元素之后的元素左移
curLen--;//表长度减1
}
//返回线性表中首次出现指定元素的索引,如果列表不包含此元素,则返回-1
@Override
public int indexOf(Object x) {
int j=0;//j为计数器
//从顺序表中的首结点开始查找,直到listElem[j]指向元素x或到达顺序表的表尾
while (j<curLen && !listElem[j].equals(x))
j++;
if (j<curLen)//判断j的位置是否位于表中
return j;
else
return -1;//x元素不在顺序表中
}
//输出线性表中的数据元素
@Override
public void display() {
for (int j=0;j<curLen;j++)
System.out.print(listElem[j]+" ");
System.out.println();
}
}
测试类
public class SqListTest {
public static void main(String[] args) throws Exception {
SqList sqList = new SqList(10);
//插入
for (int i=0;i<7;i++){
sqList.insert(i,i);
}
//展示
sqList.display();
System.out.println(sqList.length());
//读取
System.out.println(sqList.get(3));
//判断是否为空
System.out.println(sqList.isEmpty());
//删除
sqList.remove(2);
sqList.display();
//查找
System.out.println(sqList.indexOf(3));
}
}
基本上实现了线性表,但是,有一个问题就是数据只能是int
,因此,在上面的基础上,我们再对数据类型进行泛型化。
/**
* 线性表,对数据类型泛型化
*/
public class SequenceList<T> {
//默认长度
private int DEFAULT_SIZE=2;
//定义一个数组用于保存线性表的长度
private Object[] elementData;
//用于保存数组长度
private int capacity;
//保存顺序表中当前元素的个数
private int size=0;
/**
* 构造一个默认长度的空线性表
*/
public SequenceList(){
capacity=DEFAULT_SIZE;
elementData=new Object[capacity];
}
/**
* 用一个初始化元素来创建线性表
* @param element 初始化元素
*/
public SequenceList(T element){
this();//调用空的构造方法
elementData[0]=element;
size++;
System.out.println(size);
}
/**
* 用一个元素和指定长度来创建线性表
* @param element 元素
* @param initSize 指定长度
*/
public SequenceList(T element,int initSize){
capacity=1;
if (capacity<initSize)
capacity=initSize;
elementData=new Object[capacity];
elementData[0]=element;
size++;
//System.out.println(size);
}
/**
* 向顺序表中插入元素
* @param element 待插入的元素
* @param index 待插入的位置
*/
public void insert(T element,int index){
if (index<0 || index>size)
throw new IndexOutOfBoundsException("数组越界异常");
ensureCapacity(size+1);
//把index以后的元素都后移一位
System.arraycopy(elementData,index,elementData,index+1,size-index);
elementData[index]=element;
size++;
//System.out.println(size);
}
/**
* 确保数组所需长度大于数组原有长度
* @param mCapacity 数组所需长度
*/
private void ensureCapacity(int mCapacity) {
if (mCapacity>capacity){
capacity=mCapacity+2;
//System.out.println("capacity:"+capacity);
elementData= Arrays.copyOf(elementData,capacity);
}
}
/**
* 表长
* @return
*/
public int length(){
return size;
}
/**
* 向表中添加元素
* @param element
*/
public void add(T element){
insert(element,size);
}
/**
* 得到线性表存储的对象
* @param index
* @return
*/
public T get(int index){
if (index<0 || index>size)
throw new IndexOutOfBoundsException("数组越界异常");
return (T)elementData[index];
}
/**
* 判断线性表是否为空
* @return
*/
public boolean isEmpty(){
return size==0;
}
/**
* 清空线性表
*/
public void clear(){
Arrays.fill(elementData,null);
size=0;
}
/**
* 获取指定位置的前一个元素
* @param index 线性表位置,若是取线性表最后一个元素,必须index = size
* @return
*/
public T priorElem(int index){
if (index>0 && index<size+1)
return (T)elementData[index-1];
else
throw new IndexOutOfBoundsException("数组越界异常");
}
/**
* 删除指定位置的元素
* @param index
*/
public void delete(int index){
if (index<0 || index>size-1)
throw new IndexOutOfBoundsException("数组越界异常");
else
System.arraycopy(elementData,index+1,elementData, index, size-index-1);
size--;
//清空最后一个元素
elementData[size]=null;
}
/**
* 获取指定线性表位置的后一个元素
* @param index 线性表位置,若是取线性表第0个元素,必须index=-1
* @return
*/
public T nextElem(int index){
if (index==-1)
return (T)elementData[0];
else if (index<size-1&&index>-1)
return (T)elementData[index+1];
else
throw new IndexOutOfBoundsException("数组越界异常");
}
/**
* 输出数组中所有数据
*/
public void display() {
for (int j=0;j<size;j++)
System.out.print(elementData[j]+" ");
System.out.println();
}
}
测试类
public class SequenceListTest {
public static void main(String[] args) {
SequenceList sequenceList = new SequenceList(5,6);
for (int i=0;i<3;i++)
sequenceList.insert(i+2,i);
System.out.println(sequenceList.length());
sequenceList.add(10);
System.out.println(sequenceList.length());
System.out.println(sequenceList.get(4));
System.out.println(sequenceList.isEmpty());
System.out.println(sequenceList.priorElem(4));
sequenceList.display();
sequenceList.delete(2);
sequenceList.display();
System.out.println(sequenceList.nextElem(2));
}
}
链式表
单向链表
单向链表的简单操作
/**
* 单向链表
*/
public class Node02 {
String data;//值域
Node02 nextNode;//指针域
//通过构造方法创建节点
public Node02(String data, Node02 nextNode) {
this.data = data;
this.nextNode = nextNode;
}
public Node02() {
}
public Node02(String data) {
this.data = data;
}
//添加节点(尾部插入)
public void add(Node02 node02) {
if (this.nextNode == null)
this.nextNode = node02;
else
//如果当前节点不为空时,就取出当前节点下一个节点,然后调用自己的方法
this.nextNode.add(node02);
}
//显示节点
public void show() {
//通过当前这个节点,获取他的内容,然后判断他的下一个节点是否存在:递归调用
System.out.print(this.data + "---");
if (this.nextNode != null)
this.nextNode.show();
}
//在链表中查询指定节点是否存在
public boolean check(String data) {
if (data.equals(this.data)) {
return true;
} else {
if (this.nextNode != null)
//如果传入过来的数据和链表中节点的值域不相等,向下一个节点走
return this.nextNode.check(data);
else
return false;
}
}
/**
* 删除节点
* @param node02 传递一个节点(就是你要删除的节点)
* @param data 对比的参数
*/
public void delete(Node02 node02,String data){
if (this.data.equals(data)){
node02.nextNode=this.nextNode;//自己的后继要作为自己的前驱的后继
}else {
if (this.nextNode!=null)
this.nextNode.delete(this,data);
}
}
//定义一个头节点
Node02 root;//根节点
//插入节点(如果没有头节点,他就作为头节点,如果有头节点,他就往后面加)
public void firstAddNode(String data){
Node02 newNode=new Node02(data);
if (root==null){
this.root=newNode;//这个新节点作为根节点
}else {
this.root.add(newNode);//调用前面的add()(尾插法)
}
}
//显示上面的方法
public void show02() {
if (root!=null) { // 如果我们的根节点不为空的时候
this.root.show(); //显示当前节点中的内容
}
}
//查询节点
public boolean checkNode(String data){
return this.root.check(data);//从根节点开始找起
}
//删除链表中的数据
public void deleteNode(String data){
//通过传入的参数,调用方法checkNode,如果返回的是true,在当前这个链表中找到
if (checkNode(data)){
//传入的参数和根的数据一样,其实就是删除根
if (this.root.equals(data))
this.root=this.root.nextNode;//根的下一个节点做根
else
//删除的不是根节点的时候,调用前面的删除方法
this.root.delete(root,data);
}
}
}
测试类
public class NodeTest02 {
public static void main(String[] args) {
Node02 node1 = new Node02("1号车厢", null);
Node02 headNode = new Node02("火车头", node1);
Node02 node2=new Node02("2号车厢",null);
Node02 node3=new Node02("3号车厢",null);
Node02 node4=new Node02("4号车厢",null);
headNode.add(node2);
headNode.add(node3);
headNode.add(node4);
headNode.show();
System.out.println();
System.out.println(headNode.check("2号车厢"));
node3.delete(node2,"3号车厢");
headNode.show();
Node02 node02 = new Node02("火车司机", null);
headNode.firstAddNode("火车司机");
headNode.show02();
// Node02 node021 = new Node02("", null);
// node021.firstAddNode("超级火车头");
// node021.show02();
System.out.println();
Node02 node021 = new Node02();
node021.firstAddNode("火车头--->");
node021.firstAddNode("1号--->");
node021.firstAddNode("2号--->");
node021.firstAddNode("3号--->");
node021.firstAddNode("4号--->");
node021.show02();
System.out.println();
System.out.println(node021.checkNode("1号--->"));
node021.deleteNode("1号--->");
node021.show02();
}
}
/**
* 单向链表的具体的操作
*/
public class SingleLinkedList {
private int size;//链表的节点个数
private SingleNode head;//头节点
//构造方法进行初始化
public SingleLinkedList(){
this.size=0;
this.head=null;
}
//判断当前链表是否为空链表
public boolean isEmpty() {
return size==0;
}
//头插法插入节点到链表中
public String addHead(String obj){
SingleNode singleNode=new SingleNode(obj);//生成一个新的节点
if (size==0) {
head = singleNode;//如果为空的时候,链表为空链表,当前这个节点做根节点
}else{
singleNode.setNextNode(head);//让头节点作为新节点的下一个节点
head=singleNode;//新节点作为头节点来使用
}
size++;
return obj;
}
//显示节点信息
public void display(){
if (size>0){
SingleNode singleNode=head;//链表的大小不为0的时候,取到头节点
int tempSize=size;//定义出来的一个中间变量
//当前链表只有一个根节点
if (tempSize==1){
System.out.println("["+singleNode.getData()+"]");
}
while (tempSize>0){
//前这个节点和头节点一样的,打印信息
if (singleNode.equals(head))
System.out.print(singleNode.getData()+",");
//判断下一个节点不存在,直接打印
else if (singleNode.getNextNode()==null)
System.out.print(singleNode.getData());
//下一个节点还存在,就直接打印
else {
System.out.print(singleNode.getData()+",");
}
singleNode=singleNode.getNextNode();
tempSize--;
}
}else
System.out.println("链表中没有数据");
}
//删除头部元素
public String delete(){
String str=null;
if (isEmpty())
System.out.println("当前这个是一个空的链表,不需要删除!");
else {
str=(String) head.getData();
head=head.getNextNode();
size--;
}
return str;
}
//查找指定元素,找到了返回节点SingleNode,找不到返回null
public SingleNode find(String str){
SingleNode singleNode=head;//这个作为中间节点,把头节点给这个中间节点,查的时候从头节点开始
int tempSize=size;
while (tempSize>0){
if (str.equals(singleNode.getData())){
return singleNode;
}else {
singleNode=singleNode.getNextNode();
}
tempSize--;
}
return null;
}
//删除指定的元素,删除成功返回true
public boolean delete(String value){
if (size==0)
return false;
//做了两个节点,让他们初始的时候都指向头节点
SingleNode current=head;
SingleNode previous = head;
while (!current.getData().equals(value)){
if (current.getNextNode()==null)
return false;
else {
previous=current;
current=current.getNextNode();
}
}
//如果删除的节点是第一个节点
if (current==head){
head=head.getNextNode();
size--;
}else {
previous.setNextNode(current.getNextNode());
size--;
}
return true;
}
}
/**
* 单向链表中的节点类
*/
public class SingleNode {
private Object data;
private SingleNode nextNode;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public SingleNode getNextNode() {
return nextNode;
}
public void setNextNode(SingleNode nextNode) {
this.nextNode = nextNode;
}
//只构造值域,指针域通过方法给定
public SingleNode(Object data) {
this.data = data;
}
}
public class SingleNodeTest {
public static void main(String[] args) {
SingleLinkedList singleLinkedList = new SingleLinkedList();
singleLinkedList.addHead("3号车厢");
singleLinkedList.addHead("2号车厢");
singleLinkedList.addHead("1号车厢");
singleLinkedList.addHead("火车头");
singleLinkedList.display();
singleLinkedList.delete();
System.out.println();
singleLinkedList.display();
System.out.println();
System.out.println(singleLinkedList.find("1号车厢").getData());
System.out.println(singleLinkedList.delete("2号车厢"));
singleLinkedList.display();
}
}
双向链表
/**
* 双向链表
*/
public class DoublePointLink {
private Node head;//头节点
private Node tail;//尾节点
private int size;//记录当前节点
public DoublePointLink() {
this.size=0;
this.head=null;
this.tail=null;
}
//在链表头部添加节点
public void addHead(Object data){
Node newNode = new Node(data);//插入头节点的新节点
if (size==0){
head=newNode;
tail=newNode;
size++;
}else {
head.setPrev(newNode);
newNode.setNext(head);
head=newNode;
size++;
}
}
//尾部插入数据
public void addTail(Object data){
Node newNode=new Node(data);
if (size==0){
head=newNode;
tail=newNode;
size++;
}else {
tail.setNext(newNode);
newNode.setPrev(tail);
tail=newNode;
size++;
}
}
//删除链表头
public Node deleteHead(){
Node node=head;
if (size!=0){
head=head.getNext();
head.setPrev(null);
size--;
}
return node;
}
//删除链表尾
public Node deleteTail(){
Node node=tail;
if (size!=0){
tail=tail.getPrev();
tail.setNext(null);
size--;
}
return node;
}
//显示节点信息
public void display(){
if (size>0){
Node node=head;//把头部节点放在中间节点
int tempSize=size;
if (tempSize==1){
System.out.println("当前链表只有1个节点:"+node.getData());
}
while (tempSize>0){
if (node.equals(head))
System.out.print(node.getData()+"--->");
else if (node.getNext()==null)
System.out.print(node.getData());
else
System.out.print(node.getData()+"--->");
node=node.getNext();
tempSize--;
}
System.out.println();
}else
System.out.println("当前链表为空");
}
}
/**
* 链表的节点(值域和指针域)
*/
public class Node {
private Object data;//值域
private Node next;//指针域,指向后一个节点
private Node prev;//指向前一个节点
public Node(Object data) {
this.data = data;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
public Node getPrev() {
return prev;
}
public void setPrev(Node prev) {
this.prev = prev;
}
}
public class Test {
public static void main(String[] args) {
DoublePointLink doublePointLink = new DoublePointLink();
doublePointLink.addHead("火车头");
doublePointLink.addHead("火车司机");
doublePointLink.display();
doublePointLink.addTail("第一节车厢");
doublePointLink.addTail("第二节车厢");
doublePointLink.addTail("第三节车厢");
doublePointLink.addTail("第四节车厢");
doublePointLink.display();
doublePointLink.deleteHead();
doublePointLink.display();
doublePointLink.deleteTail();
doublePointLink.deleteTail();
doublePointLink.display();
}
}
循环链表
/**
* 循环链表
* 约瑟夫问题(隔几个淘汰一个)
* 例:罗马人攻占了乔塔帕特,41人藏在一个山洞中躲过了这场浩劫。
* 这41个人中为了表示不向罗马人屈服,决定集体自杀。
* 大家决定了一个自杀方案,所有这41人围成一个圆圈,由第一个人开始顺时针报数,
* 每报数为3的人就立刻自杀,然后由下一个人重新开始报数任然是每报数为3的人就立刻自杀,......,
* 直到所有人都自杀死亡为止.
*/
public class CircularLinkedList {
//内部类 节点的值域与指针域
class node{
node next;
int data;
public node getNext() {
return next;
}
public void setNext(node next) {
this.next = next;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
}
/**
* 创建循环链表的过程
* @param totalCol 循环链表里的个数
* @return
*/
public node createNodes(int totalCol){
node head=null;
node[] nodes = new node[totalCol];//对象数组,存放每个的节点
//往数组中放入节点
for (int i=0;i<totalCol;i++){
nodes[i]=new node();
nodes[i].data=i+1;//给循环链表中的值域放入值
if (i==0)
head=nodes[i];
else
nodes[i-1].next=nodes[i];
}
nodes[totalCol-1].next=head;//尾节点与头节点相连,构成循环链表
return head;
}
//开始进行判断
public void begin(int total){
int sort=0;//数组中的第几个人
int n=total;//数组长度
int m=3;//相隔数量
m%=n;//取模运算(主要是防止n<m时的操作,比如n=1时)
node head = createNodes(total);//创建节点
while (head.next!=head){
for (int i=1;i<m-1;i++)
head=head.next;//下移操作
node temp=head.next;
System.out.println("第"+(++sort)+"个自杀的为:"+temp.data);
head.next=temp.next;
head=head.next;
}
System.out.println("第"+(++sort)+"个自杀的为:"+head.data);
}
}
public class Test {
public static void main(String[] args) {
CircularLinkedList circularLinkedList = new CircularLinkedList();
circularLinkedList.begin(41);
}
}