链表

单链表

概念:单链表就是一个结点存放元素的值和指向下一个结点的引用!分为带头结点和非带头结点
单链表要实现插、删、查、改!
插和删除都需要修改存放在结点的引用地址值,根据链表的数据结构可以知道查和改是需要遍历的!

public class SingleLinkedList {
	private int size=0;//有效结点个数,不包括头结点
	private int loc=0;
	private HeroNode begainnode= new HeroNode(-1,"");
	
	public SingleLinkedList() {
		size=0;
		loc=0;
	}
	
	//在末尾插入元素
	public void addlast(HeroNode hero) {
		HeroNode temp=begainnode;
		while(true) {
			if(temp.nextnode==null) {
				break;	
			}
			temp=temp.nextnode;
		}
		//循环用于获取最后位置的结点
		temp.nextnode=hero;//这种思路更好,代码块之间耦合更低	
		size++;
	}
	
	//在指定位置插入,(在指定位置后面插入更简单)
	public void addlocation(int l, HeroNode hero) {
		int s = 0;
		if (l + 1 > size) {
			System.out.println("没有这个位置");
			return;
		} else {
			HeroNode temphero = getHeroNode(l - 1);// 这个位置的前一个结点
			HeroNode t=temphero.nextnode;
			temphero.nextnode = hero;
			hero.nextnode=t;
			size++;
		}
	}
	
	//获取下标为l的结点,从0开始
	public HeroNode getHeroNode(int l) {
		int s=-1;
		HeroNode temphero=begainnode;
		while (true) {
			if(s>=size||l==s) {
				break;
			}
			temphero = temphero.nextnode;
			s++;
		}
		return temphero;
	}
	
	//删除下标为location的结点
	public HeroNode del(int location) {
		if(location>size-1) {
			System.out.println("删除错误");
			return null;
		}else {
			HeroNode temphero = getHeroNode(location - 1);
			HeroNode h=temphero.nextnode;
			temphero.nextnode=temphero.nextnode.nextnode;
			size--;
			return h;
		}
	}
	
	//删除尾结点
	public HeroNode dellast(){
		HeroNode temp=del(size-1);
		return temp;
	}
	
	//列出全部元素
	public void listall() {
		HeroNode hero=begainnode;
		for(int i=0;i<size;i++) {
			hero=hero.nextnode;
			System.out.println(hero);
		}
	}
	
	//测试代码
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SingleLinkedList  sll=new SingleLinkedList();
		for(int i=0;i<5;i++) {
			HeroNode h=new HeroNode(i,"hero"+i);
			sll.addlast(h);
		}
		HeroNode h=new HeroNode(8,"herox");
		sll.addlocation(1, h);
		sll.listall();
		System.out.println("");
		sll.del(0);
		sll.listall();
	}
}

class HeroNode{
	public int numb;
	public String name;
	public HeroNode nextnode;
	public HeroNode(int n,String s) {
		this.numb=n;
		this.name=s;
		this.nextnode=null;
	}
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "英雄\t"+numb+"\t"+name+"\t";
	}
	
}

双链表

带head结点的双链表就是结点有上一个结点和下一个结点的引用值!

/*
 * 和单边二叉树有点像
 */
public class MyLinkedList<AnyType> implements Iterator<AnyType> {
	private Node<AnyType> beginMarker;
	private Node<AnyType> endMarker;
	private int modCount=0;
	private int theSize;
	
	//初始化
	public MyLinkedList() {
		doclear();
	}
	
	private void doclear() {
		beginMarker=new Node<AnyType>(null,null,null);
		endMarker=new Node<AnyType>(null,beginMarker,null);
		beginMarker.next=endMarker;
		modCount++;
		theSize=0;
	}
	//重新初始化文件
	public void clear() {
		doclear();
	}
	
	public void addBefore(Node<AnyType> p,AnyType x) {
		//这就创建一个新的节点
		Node<AnyType> newnode=new Node<AnyType>(x,p.prev,p);
		p.prev.next=newnode;
		p.prev=newnode;
		theSize++;
		modCount++;		
	}
	
	public int size() {
		return theSize;
	}
	public boolean add(AnyType x) {
		add(size(),x);
		return true;
	}
		
	private void add(int index, AnyType x) {
		// TODO Auto-generated method stub
		addBefore(getNode(index,0,size()),x);		
	}

	public AnyType remove(int index) {
		return remove(getNode(index));		
	}
	
	public AnyType get(int index) {
		return getNode(index).data;
	}
	
	//删除节点,并返回删除节点的值
	public AnyType remove(Node<AnyType> node) {		
		node.next.prev=node.prev;
		node.prev.next=node.next;
		theSize--;
		modCount++;
		return node.data;
	}
	
	private Node<AnyType> getNode(int index) {		
		return getNode(index,0,size()-1);
	}
		
	public Node<AnyType> getNode(int index,int lower,int upper) {
		Node<AnyType> p;
		if(index<lower||index>upper) {
			throw new IndexOutOfBoundsException();
		}		
		if(index<size()/2) {
			p=beginMarker.next;
			for(int i=0;i<index;i++) {
				p=p.next;
			}			
		}else {
			p=endMarker;
			for(int i=size();i>index;i--) {
				p=p.prev;
			}
		}		
		return p;		
	}
	
	public java.util.Iterator<AnyType> iterator(){
		return new LinkedListIterator();
	}
	
	private class LinkedListIterator implements java.util.Iterator<AnyType>{
		private Node<AnyType> currentnode=beginMarker.next;
		private int modcount=modCount;
		private boolean okToRemove=false;
		
		@Override
		public boolean hasNext() {
			return currentnode!=endMarker;
		}

		@Override
		public AnyType next() {
			if(modCount!=modcount) {
				throw new java.util.ConcurrentModificationException();
			}
			if(!hasNext()) {
				throw new java.util.NoSuchElementException();
			}
			AnyType item=currentnode.data;
			currentnode=currentnode.next;
			okToRemove=true;
			return item;
		}
		
		public void remove() {
			if(modCount!=modcount) {
				throw new java.util.ConcurrentModificationException();
			}
			if(!okToRemove) {
				throw new IllegalStateException();
			}
			
			MyLinkedList.this.remove(currentnode.prev);
			modcount++;
			okToRemove=false;
			
		}	
	}
	
	@Override
	public boolean hasNext() {
		// TODO Auto-generated method stub
		return false;
	}
	@Override
	public AnyType next() {
		// TODO Auto-generated method stub
		return null;
	}
		
	//每一个节点的信息
	private static class Node<AnyType>{
		public Node(AnyType d,Node<AnyType> p,Node<AnyType> n) {
			data=d;
			prev=p;
			next=n;			
		}	
		private AnyType data;
		public Node<AnyType> prev;
		public Node<AnyType> next;	
	}
}

单向环形(循环)链表

丢手绢、约瑟夫问题:编号为1、2、到n的n个人,约定第k个人从1开始报数,数到m的那个人出列,下一个人从1开始开始数数,依次类推,知道全部出列,给出出列顺序!
这个一个循环报数的问题,并且相邻的编号之前是有前后关系的,这里面还涉及删除操作,是可以用环形链表来实现这个问题。(三种实现方式)

package sparesearray;

import java.util.ArrayList;

/*
 * SingleLinkedList of no headnode
 */

public class Josephus {
	Joheronode begainnode;
	int n;
	int k;
	int m;
	public ArrayList<Joheronode> list=new ArrayList<>();
	//
	public Josephus(int size,int k,int m) {
		this.n=size;
		this.k=k;
		this.m=m;
		init(size);//让一定数量的对象形成循环链表的关系,只有知道其中一个对象,就可以列出所有对象
		setbegainnode(k);
		listinit();
		removeall(m);
	}
	
	//不带头结点,初始化
	public void init(int size) {
		begainnode =new Joheronode(1);
		Joheronode j=begainnode;
		Joheronode temp;
		for(int i=2;i<=size-1;i++) {
			temp=new Joheronode(i);
			j.nextnode=temp;
			j=temp;
		}
		temp=new Joheronode(size);
		j.nextnode=temp;
		temp.nextnode=begainnode;
	}
	
	//列出初始值
	public void listinit() {
		Joheronode temp=begainnode;
		for(int i=1;i<=n;i++) {
			System.out.println(temp);
			temp=temp.nextnode;
		}
	}
	
	//先获取第k个结点
	public Joheronode getlocnode(int k) {
		Joheronode temp=begainnode;
		for(int i=2;i<=k;i++) {
			temp=temp.nextnode;
		}
		return temp;
	}
	
	//让第k个结点为初始结点
	public void setbegainnode(int k) {
		Joheronode temp=begainnode;
		for(int i=2;i<=k;i++) {
			temp=temp.nextnode;
		}
		begainnode=temp;
	}
	
	//删除第m个结点,m大于等于1
	public Joheronode remove(int m) {
		Joheronode temp=begainnode;
		Joheronode t;
		int k=m%n;
		if(n==1) {
			list.add(begainnode);
		} else {
//			if (k == 0) {
//				t = getlocnode(n - 1);
//				temp = t.nextnode;
//				begainnode = temp.nextnode;
//				t.nextnode = t.nextnode.nextnode;
//
//			} else if (k == 1) {
//				t = getlocnode(n);
//				temp = t.nextnode;
//				begainnode = temp.nextnode;
//				t.nextnode = t.nextnode.nextnode;
//			} else {
//				t = getlocnode(k - 1);
//				temp = t.nextnode;
//				begainnode = temp.nextnode;
//				t.nextnode = t.nextnode.nextnode;
//			}
			
			t = getlocnode(k==1?n:(n+k-1)%n);
			temp = t.nextnode;
			begainnode = temp.nextnode;
			t.nextnode = t.nextnode.nextnode;
			
			list.add(temp);
		}
		n--;
		return temp;
	}
		
	public void removeall(int m) {
		while(n>0) {
			remove(m);
		}
	}
	
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Josephus j=new Josephus(5,2,2);
		System.out.println("删除");
//		for(int i=1;i<6;i++) {
//			j.remove(2);
//		}
		System.out.println(j.list);		
	}
}

class Joheronode{
	private int number;
	public Joheronode nextnode;
	public Joheronode(int n) {
		this.number=n;
	}	
	@Override
	public String toString() {
		return "hero "+number+"\t";
	}
}

另外的解法

递归方法解决约瑟夫问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值