单链表原理解析及应用

单链表结构在实际应用中还是很广泛的,而且数据插入和删除的效率相比数组类型要好很多。

目录

一、单链表概念

二、单链表的增改删操作

三、单链表的应用


一、单链表概念

那什么是单链表呢?单链表是一种链式的存储结构,存储的数据以节点的方式来表示,而每个节点由数据域和指针域两部分组成。数据域中保存着被存储的数据,而指针域中保存着下一个节点的地址,这样每个节点就形成了一个链状。

二、单链表的增改删操作

注意:图中Data我们表示当前数据的内存地址,而Pointer我们表示所指向数据节点的内存地址

添加数据:如图所示,蓝色部分是原始数据链,第一个数据指针指向了Data=101的数据节点。现在如果想在两者之间添加数据,需要将原始数据的链接部分断开,也就是更改第一个数据节点指针域的指向。从图可以看出,新增的数据Data=301,我们只需要将第一个数据节点指针域指向301即可,此时我们还需要将新增数据的指针域指向101,这样就形成了一个新的数据链,从而达到了增加数据的操作

修改数据:如图所示,蓝色链状为单链表的原始数据,现在我想更改第二个位置的数据,我只需要将待更改数据前后链接的两条链断开,而断开的意义就是更改前一个数据指针的指向。如图,第一个数据指针从指向101改为401,而401的地址就是更改后的数据。而黄颜色的数据节点指向201,从而形成了一个新数据链,这样就达到了修改数据的目的

删除数据:如果增加数据和修改数据明白的话,输出数据就比较好理解了。如图所示,如果想要删除第二数据,只需要将第一个数据和第二个数据之间的链接断开,即更改第一个数据的指向为201;断开第二个和第三个之间的链接,即将第二数据的指针指向置为空。这样就达到了删除数据的目的。

三、单链表的应用

在Android中的MessageQueue就是使用的链表结构,查看它的源码可以看到有很多链表的增删改查。虽然它的名字是消息队列,但是其实是一个链表结构。这里我就不进行源码解析了。我主要从算法和单链表结构的特点来做一个发牌并进行排序的应用。

首先创建一个扑克的类Poker.java,包括了两个属性值type和num

type:0表示大小王,1表示红桃,2表示黑桃,3表示方片,4表示草花

num:type为0时,0表示大王,1表示小王;type不为0时,依次类推即可

重写了toString方法

public class Poker {
	public Poker(int type,int num) {
		super();
		this.num = num;
		this.type = type;
	}
	private int num;
	private int type;
	
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public int getType() {
		return type;
	}
	public void setType(int type) {
		this.type = type;
	}
	@Override
	public String toString() {
		StringBuffer item_describeBuffer = new StringBuffer();
		switch(type) {
			case 1:
				item_describeBuffer.append("红桃");
				break;
			case 2:
				item_describeBuffer.append("黑桃");
				break;
			case 3:
				item_describeBuffer.append("方片");
				break;
			case 4:
				item_describeBuffer.append("草花");
				break;
		}
		switch(num) {
			case 0:
				item_describeBuffer.append("A");
				break;
			case 10:
				item_describeBuffer.append("J");
				break;
			case 11:
				item_describeBuffer.append("Q");
				break;
			case 12:
				item_describeBuffer.append("K");
				break;
			default:
				item_describeBuffer.append(num+1);
				break;
		}
		if(type==0) {
			item_describeBuffer.delete(0, item_describeBuffer.length());
			if(num==0) {
				item_describeBuffer.append("大王");
			}else if(num==1) {
				item_describeBuffer.append("小王");
			}
		}
		return item_describeBuffer.toString();
	}
}

下面是man.java方法,主要功能是创建54张牌,随机选择3张牌,发牌及排序,而链表的应用主要是pokerSort排序方法上

public class Main {
	private static int poker_num = 13;//扑克中每种类型最多有13张
	private static int type = 5;//扑克中一共有5种类型 包括大小王
	private static LinkedList<Poker>poker;//一副扑克
	private static LinkedList<Poker>lastThree;//最后三张牌
	public static void main(String[] args) {
		 poker = generatePoker();
		 lastThree = lastThreePokerItem();
		 System.out.println("最后三张牌:"+lastThree);
		 threeUserPoker();
	}
	/**
	 * 生成一副扑克
	 */
	private static LinkedList<Poker> generatePoker() {
		LinkedList<Poker>poker = new LinkedList<Poker>();
		for (int i = 0; i < type; i++) {
			for (int j = 0; j < poker_num; j++) {
				Poker poker_item = new Poker(i,j);
				poker.add(poker_item);
				if(i==0&&j>=1)
					break;
			}
		}
		return poker;
	}
	/**
	 * 抽出最后三张牌
	 */
	private static LinkedList<Poker> lastThreePokerItem() {
		LinkedList<Poker>lastThreePokerList = new LinkedList<Poker>();
		for(int i = 0;i<3;i++) {
			Poker itemPoker = poker.remove(new Random().nextInt(poker.size()));
			lastThreePokerList.add(itemPoker);
		}
		return lastThreePokerList;
	}
	/**
	 * 三个玩家的牌
	 */
	private static void threeUserPoker() {
		int every_user_num = poker.size()/3;
		for(int i = 0;i<3;i++) {
			LinkedList<Poker>userPokers = new LinkedList<Poker>();
			for(int j = 0 ;j<every_user_num;j++) {
				userPokers.add(poker.remove(new Random().nextInt(poker.size())));
			}
			pokerSort(i,userPokers);
		}
	}
	/**
	 * 排序
	 * @param poker
	 */
	private static void pokerSort(int position,LinkedList<Poker>poker) {
		//一共有多少个数,就有多少组
		LinkedList[] numLinkedLists = new LinkedList[13];
		for (int i = 0; i < numLinkedLists.length; i++) {
			numLinkedLists[i] = new LinkedList<Poker>();
		}
		//根据数的大小进行分组
		while(poker.size()>0) {
			Poker itemPoker = poker.remove();
			numLinkedLists[itemPoker.getNum()].add(itemPoker);
		}
		for (int i = 0; i < numLinkedLists.length; i++) {
			poker.addAll(numLinkedLists[i]);
		}
		//一共有多少类型,就有多少组
		LinkedList[] typeLinkedLists = new LinkedList[5];
		for (int i = 0; i < typeLinkedLists.length; i++) {
			typeLinkedLists[i] = new LinkedList<Poker>();
		}
		//根据类型进行分组
		while (poker.size()>0) {
			Poker itemPoker = poker.remove();
			typeLinkedLists[itemPoker.getType()].add(itemPoker);
		}
		for (int i = 0; i < typeLinkedLists.length; i++) {
			poker.addAll(typeLinkedLists[i]);
		}
		System.out.println("玩家"+(position+1)+":"+poker);
	
	}
}

输出结果如下

最后三张牌:[方片6, 红桃4, 草花3]
玩家1:[大王, 红桃A, 红桃3, 红桃6, 红桃8, 黑桃3, 黑桃6, 黑桃7, 方片A, 方片7, 草花A, 草花2, 草花4, 草花6, 草花J, 草花Q, 草花K]
玩家2:[小王, 红桃5, 红桃7, 红桃10, 红桃K, 黑桃2, 黑桃5, 黑桃10, 黑桃J, 黑桃Q, 方片2, 方片5, 方片8, 方片9, 方片J, 方片K, 草花9]
玩家3:[红桃2, 红桃9, 红桃J, 红桃Q, 黑桃A, 黑桃4, 黑桃8, 黑桃9, 黑桃K, 方片3, 方片4, 方片10, 方片Q, 草花5, 草花7, 草花8, 草花10]

单链表的介绍就到此结束了,欢迎提问,欢迎纠错!

猜你喜欢

转载自blog.csdn.net/qq_32019367/article/details/88538776