单链表结构在实际应用中还是很广泛的,而且数据插入和删除的效率相比数组类型要好很多。
目录
一、单链表概念
那什么是单链表呢?单链表是一种链式的存储结构,存储的数据以节点的方式来表示,而每个节点由数据域和指针域两部分组成。数据域中保存着被存储的数据,而指针域中保存着下一个节点的地址,这样每个节点就形成了一个链状。
二、单链表的增改删操作
注意:图中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]
单链表的介绍就到此结束了,欢迎提问,欢迎纠错!