链结点在链表中,每个数据项都被包含在‘点“中,一个点是某个类的对象,这个类可认叫做 LINK。
因为一个链表中有许多类似的链结点,所以有必要用一个不同于链表的类来表达链结点。
每个 LINK 对象中都包含一个对下一个点引用的字段(通常叫做next)
但是本身的对象中有一个字段指向对第一个链结点的引用单链表是一种顺序存取的结构,
为找第 i个数据元素,必须先找到第i-1个数据元素。
因此,查找第i个数据元素的基本操作为:移动指针,比较j 和i
1、链接存储方法
链接方式存储的线性表简称为链表(LinkedList )。
链表的具体存储表示为:
① 用一组任意的存储单元来存放线性表的结点(这组存储单元既可以是连续的,
也可以是不连续的)
② 链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻
辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信
息(称为指针(pointer )或链(link) )
注意:
链式存储是最常用的存储方式之一,它不仅可用来表示线性表,而且可用来表示
各种非线性的数据结构。
2 、链表的结点结构
┌──┬──┐
│data │next │
└──┴──┘
data 域--存放结点值的数据域
next 域--存放结点的直接后继的地址(位置)的指针域(链域)
注意:
①链表通过每个结点的链域将线性表的 n 个结点按其逻辑顺序链接在一起的。
②每个结点只有一个链域的链表称为单链表(Single Linked List )。
3 、头指针 head 和终端结点指针域的表示
单链表中每个结点的存储地址是存放在其前趋结点 next 域中,而开始结点无前
趋,故应设头指针 head 指向开始结点。
注意:
链表由头指针唯一确定,单链表可以用头指针的名字来命名。
【例】头指针名是 head 的链表可称为表 head 。
终端结点无后继,故终端结点的指针域为空,即 NULL 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
public
class
LinkList<T> {
public
class
Node{
//定义节点
private
T data;
private
Node next;
public
Node(){
}
public
Node(T data,Node next){
this
.data=data;
this
.next=next;
}
}
private
Node header;
//头节点
private
Node tail;
//尾节点
private
int
size;
//链表大小
//构造函数初始化数据
public
LinkList(){
header=
null
;
tail=
null
;
}
public
LinkList(T element){
header=
new
Node(element,
null
);
tail=header;
size++;
}
//链表长度
public
int
length(){
return
size;
}
//返回指定位置index的节点
public
T get(
int
index){
return
getNodeByIndex(index).data;
}
private
Node getNodeByIndex(
int
index) {
if
(index<
0
||index>size-
1
){
throw
new
IndexOutOfBoundsException(
"线性表索引越界"
);
}
Node current=header;
for
(
int
i=
0
;i<size&¤t!=
null
;i++,current=current.next){
if
(i==index){
return
current;
}
}
return
null
;
}
//返回element在链表的位置,-1表示不存在
public
int
locate(T element){
Node current=header;
for
(
int
i=
0
;i<size&¤t!=
null
;i++,current=current.next){
if
(current.data==element){
return
i;
}
}
return
-
1
;
}
//在index位置插入节点element
public
void
insert(T element,
int
index){
if
(index<
0
||index>size){
throw
new
IndexOutOfBoundsException(
"线性表索引越界"
);
}
if
(header==
null
){
add(element);
}
else
{
if
(index==
0
){
addAtHeader(element);
}
else
{
Node prev=getNodeByIndex(index-
1
);
prev.next=
new
Node(element,prev.next);
size++;
}
}
}
//采用尾插法为链表添加新节点
private
void
add(T element) {
// TODO Auto-generated method stub
if
(header==
null
){
header=
new
Node(element,
null
);
tail=header;
}
else
{
Node newNode=
new
Node(element,
null
);
tail.next=newNode;
tail=newNode;
}
size++;
}
//采用头插法为链表添加新节点
private
void
addAtHeader(T element){
header=
new
Node(element,header);
if
(tail==
null
){
tail=header;
}
size++;
}
//删除index位置的节点
public
T delete(
int
index){
if
(index<
0
||index>size-
1
){
throw
new
IndexOutOfBoundsException(
"线性表索引越界"
);
}
Node del=
null
;
if
(index==
0
){
del=header;
header=header.next;
}
else
{
Node prev=getNodeByIndex(index-
1
);
del=prev.next;
prev.next=del.next;
del.next=
null
;
}
size--;
return
del.data;
}
//从链表后面删除一个节点
public
T remove(){
return
delete(size-
1
);
}
//是否为空
public
boolean
empty(){
return
size==
0
;
}
//清空链表
public
void
clear(){
header=
null
;
tail=
null
;
size=
0
;
}
public
String toString(){
if
(empty()){
return
"[]"
;
}
else
{
StringBuilder sb=
new
StringBuilder(
"["
);
for
(Node current=header;current!=
null
;current=current.next){
sb.append(current.data.toString()+
", "
);
}
int
len=sb.length();
return
sb.delete(len-
2
, len).append(
"]"
).toString();
}
}
public
static
void
main(String[] args) {
LinkList<String> list=
new
LinkList<String>();
list.insert(
"aaa"
,
0
);
list.add(
"bbb"
);
list.add(
"ccc"
);
System.out.println(list.toString());
list.insert(
"ddd"
,
1
);
System.out.println(list.toString());
list.delete(
2
);
System.out.println(list.toString());
System.out.println(
"ccc在链表中的位置:"
+list.locate(
"ccc"
));
System.out.println(
"链表中索引2处的元素:"
+list.get(
2
));
}
}
|