java实现单向链表与链栈
准备复习数据结构,从链表开始,想着csdn看看别人是咋写的,一搜一大堆,每个人写的都不一样,当然我可能写的也很奇葩,我就是根据我学C语言的时候写的
一、单向链表
1、定义链表节点
public class Node {
public int data;//数据域
public Node next;//指针域
public Node(int data){
this.data=data;
}
}
表节点分为一个数据域和一个指针域。数据域的值我定义的是int型;指针域的值是next,是表节点类型(Node类型)
2、链表的创建及一些操作
在这里,每增加一个节点我使用的是尾插法
public class Linklist {
Node head;
//根据一个整数值创建一个链表
public Node createlink(int a){
head=new Node(a);
head.next=null;
return head;
}
//增加一个链表节点(尾插法)
public void addNode(int a,Node head){
// last最后一个尾元素,tmp存储待增加的元素
Node last,tmp;
//找到最后一个位置进行尾插
for(last=head;last.next!=null;last=last.next);
tmp=new Node(a);
last.next=tmp;
}
//链表的长度
public int linklength(Node node){
Node tmp;
int length=0;
if(node ==null){
return length;
}else{
for(tmp=node;tmp!=null;tmp=tmp.next){
length++;
}
return length;
}
}
//删除key位置上的节点
public void deletelink(int key,Node node){
//用来暂存链表的首元素,进行遍历使用
Node tmp;
//判断删除的节点位置是否合理
if(key<=0&&key>=linklength(node)){
System.out.println("你想删除的节点位置不存在!");
}else{
int count=1;
for(tmp=node;count!=key-1;tmp=tmp.next);//找到要删除元素的前置节点
tmp.next=tmp.next.next;
}
}
//打印链表
public void printlink(Node node){
Node tmp;
for(tmp=node;tmp!=null;tmp=tmp.next){
System.out.print(tmp.data+"\t");
}
}
//测试
public static void main(String[] args) {
Linklist linklist =new Linklist();
Node head= linklist.createlink(8);
linklist.addNode(3,head);
linklist.addNode(2,head);
linklist.addNode(5,head);
linklist.addNode(8,head);
linklist.printlink(head);
int linklength= linklist.linklength(head);
System.out.println("\n链表的的长度是:"+linklength);
linklist.deletelink(2,head);
linklist.printlink(head);
}
}
- 单向链表的优点:易删除和增加节点
- 链表的缺点:占空间大,既要存指针域又要存数值域;访问慢,必须从表头开始一个一个遍历
- 使用环境:适用于增加和删除节点
二、链栈
1、定义栈节点
public class Node {
public int data;//数据域
public Node next;//指针域
public Node(){
this.data=-1;
}
public Node(int data){
this.data=data;
this.next=null;
}
}
这里定义链栈节点和链表节点类似,都是一个数据域和一个指针域。
2、创建链栈及一些操作
public class LinkStack {
Node base;//栈底指针
Node top;//栈顶指针
int size;//栈的大小
//构造一个空的链栈
public LinkStack(){
this.base=null;
this.top=null;
this.size=0;
}
//创建一个空的链栈
public void createStack(){
base=top=null;
size=0;
}
//向链栈中放入一个整数值
public void push(int a){
Node tmp=new Node(a);
if(base==null){
base=tmp;
top=tmp;
}else{
top.next=tmp;
top=tmp;
}
//链栈的大小就加一
this.size++;
}
//弹出栈顶的值
public void pop(){
Node tmp;
if(this.size<=0){
System.out.println("栈空!");
}else{
for(tmp=base;tmp.next!=top;tmp=tmp.next);
tmp.next=tmp.next.next;
top=tmp;
size--;
}
}
//入栈方向打印链栈
public void printStack(){
Node tmp;
System.out.println("链栈的入栈顺序为:"+"\n");
for(tmp=base;tmp!=null;tmp=tmp.next){
System.out.print(tmp.data+"\t");
}
}
//出栈方向打印链栈
public void printStack1(){
Node tmp,flag;
System.out.println("链栈的出栈顺序为:"+"\n");
for(tmp=base,flag=top;tmp.next!=flag;tmp=tmp.next){
System.out.println(flag.data);
flag=tmp;
}
}
//测试
public static void main(String[] args) {
LinkStack stack=new LinkStack();
stack.createStack();
System.out.println(stack.size);
stack.push(2);
stack.push(5);
stack.push(3);
stack.push(8);
stack.push(9);
stack.push(9);
System.out.println(stack.size);
stack.printStack();
stack.pop();
stack.pop();
System.out.println(stack.size);
}
}
链栈的优点:不存在因栈满而溢出的情况
链栈的缺点:栈空间大,只能从栈顶进行删除与插入元素(可以说这是大多数栈的特点,读者可以尝试通过两个双向栈实现链表)
三、单向链队列
1、定义队列节点
队列的节点和栈节点的定义相似,都是一个值域和数据域,只不过在创建的时候,链栈创建的是base栈底指针和top栈顶指针,base指针不动,入栈出栈栈顶指针来回指。而创建链队列的时候创建的是front队首指针和rear队尾指针,出队时队首指针变动,入队时队尾指针变动。
public class Node {
int data;//存储数据域
Node next;//存储指针域
Node(int data){
this.data=data;
next=null;
}
}
2、创建链栈及一些操作
public class Queue {
Node front;//存储队首元素
Node rear;//存储队尾元素
Queue(){
front=null;
rear=null;
}
//创建一个空队列
public void createQueue(){
front=rear=null;
}
//增加元素,从队尾增加
public void enQueue(int num){
Node tmp=new Node(num);
if(front==null){
front=rear=tmp;
}else{
rear.next=tmp;//从队尾开始增加节点
rear=tmp;
}
}
//出队列,从队首出队
public void deQueue(){
if(this.getSize()<=0){
System.out.println("此队列为空,不能进行出队");
}else {
front=front.next;//直接让原来的队首元素指向下一个元素即可
}
}
//打印队列
public void printQueue(){
Node tmp;
if(this.getSize()<=0){
System.out.println("此队列为空!");
}else{
System.out.println("\ns队列遍历如下:");
//从队首向队尾开始遍历
for(tmp=front;tmp!=null;tmp=tmp.next){
System.out.print(tmp.data+"\t");
}
}
}
//获取队列的长度大小
public int getSize(){
Node tmp;
int count=1;
if(front==null){
return count-1;
}else{
for(tmp=front;tmp!=rear;tmp=tmp.next){
count++;
}
return count;
}
}
//测试
public static void main(String[] args) {
Queue queue=new Queue();
queue.createQueue();
queue.enQueue(9);
queue.enQueue(4);
queue.enQueue(2);
queue.enQueue(5);
queue.enQueue(1);
queue.enQueue(8);
System.out.println("\n队列的长度为:"+queue.getSize());
queue.printQueue();
queue.deQueue();
queue.printQueue();
System.out.println("\n队列的长度为:"+queue.getSize());
}
}
链队列的优点:相对于链栈可对表进行双向操作
链队列的缺点:也只能从表两头进行操作
使用环境:可以考虑排队的问题