普通单向链表应该包含的数据和方法:
结点类(Node):
属性:
AnyType value; //任意类型的数据
Node* next; //指向下一个节点的指针
方法:
构造方法 Node(AnyType* value, Node* next);
链表类(LinkedList):
Node* head; //链表头结点的指针
Node* tail; //链表尾结点的指针,可选
int length; //链表长度,可选
int isEmpty(); //链表是否为空
int contains(); //链表是否包含某个值
void addToHead(AnyType value); //向链表头添加数据
void addToTail(AnyType value); //向链表尾添加数据
void addNode(AnyType value, int index) //向链表指定下标处添加数据
int deleteFromHead(); //从链表头删除一个数据,返回被删除的数据
int deleteFromTail(); //从链表尾删除一个数据,返回被删除的数据
int deleteNode(); //删除指定下标处的数据,返回被删除的数据
实现每种方法的思路:
1、因为LinkedList类的属性有:head,tail,length
所以要根据不同情况更新三个属性
2、所以每种方法,都要处理:
1)head发生变化
2)tail发生变化
的情况
下方是Java代码:
//链表类
public class LinkedList {
//
Node head; //链表头结点的指针
Node tail; //链表尾结点的指针,可选
int length; //链表长度,可选
int isEmpty() { //链表是否为空
//头结点为空,链表为空
return head == null ? 1 : 0;
};
int contains(int value) { //链表是否包含某个值
//遍历链表,查找值
for (Node now=head; now!=null; now=now.next)
if (now.value == value)
return 1;
return 0;
}
void addToHead(int value) { //向链表头添加数据
//如果链表为空,更新head和tail
if (head == null)
head = tail = new Node(value);
//否则直接添加
else
this.head = new Node(value, this.head);
this.length++;
}
void addToTail(int value) { //向链表尾添加数据
//如果链表为空,更新head和tail
if (head == null)
head = tail = new Node(value);
//否则直接添加
else
tail = tail.next = new Node(value);
length++;
}
void addNode(int value, int index) { //向链表指定下标处添加数据
//如果要添加的下标不合法,直接返回
if (index <= 0) return;
//如果链表为空,且在第一个位置插入
if (head == null && index == 1) {
head = tail = new Node(value);
length++;
return ;
}
//如果链表为空,要在非法位置插入
else if (head == null && index != 1) {
return ;
}
//如果在头部插入,更新head
if (index == 1) {
head = new Node(value, head);
length++;
return ;
}
//在其他部位插入
Node aheadOfAdd = null;
int cnt = 1;
//循环查找链表,找到index-1位置的结点,存入aheadOfAdd
//使得循环停止的条件有两个:
//情况1:aheadOfAdd=null单独成立,说明要添加的序号已经超出现有的链表长度
//情况2:cnt+1=index成立且aheadOfAdd为空,说明要插入的位置刚好在链表尾向后第二个位置
//情况3:cnt+1=index单独成立,说明找到了要插入的结点的前一个结点
for (aheadOfAdd=head,cnt=1; aheadOfAdd!=null&&cnt+1<index; cnt++,aheadOfAdd=aheadOfAdd.next);
//System.out.println(cnt);
//System.out.println(aheadOfAdd);
//情况1
if (index != cnt+1)
return ;
//情况2
if (aheadOfAdd == null)
return ;
//情况3
aheadOfAdd.next = new Node(value, aheadOfAdd.next);
length++;
if (aheadOfAdd.next.next == null) tail = aheadOfAdd.next;
}
int deleteFromHead() { //从链表头删除一个数据,返回被删除的数据
int deletedValue = -1;
//链表为空,直接返回
if (head == null)
return -1;
deletedValue = head.value;
//链表只有一个元素,删除并更新head和tail
if (head == tail)
head = tail = null;
//删除头部
else
head = head.next;
length--;
return deletedValue;
}
int deleteFromTail() { //从链表尾删除一个数据,返回被删除的数据
int deletedValue = -1;
//链表为空,直接返回
if (head == null)
return -1;
//链表只有一个元素,删除并更新head和tail
if (head == tail) {
deletedValue = head.value;
head = tail = null;
}
//删除尾部
else {
Node now = null;
//遍历找到尾部
for (now = head; now.next!=tail; now=now.next);
deletedValue = now.next.value;
now.next = null;
tail = now;
}
length--;
return deletedValue;
}
int deleteNode(int index) { //删除指定下标处的数据,返回被删除的数据
//下标不合法,直接返回
if (index <= 0) return -1;
int deletedValue = -1;
int cnt = 1;
Node now = null;
//链表为空,直接返回
if (head == null)
return -1;
//链表只有一个结点且要删除那个结点
if (head == tail && index == 1) {
deletedValue = head.value;
head = tail = null;
}
//如果要删除第一个结点,那么下方循环将会出现问题,所以单独处理
if (index == 1) {
deletedValue = head.value;
head = head.next;
}
else {
//循环找到要删除的那个结点
//循环终止的条件有两个
//情况1:now==null成立,找到要删除的结点之前已经到了链表尾
//情况2:cnt+1=index成立,找到了要删除的结点的前一个结点
for(now=head; cnt+1<index && now!=null; cnt++,now=now.next);
//情况1
if(now == null) return -1;
//情况2
deletedValue = now.next.value;
if (now.next == tail)
tail = now;
now.next = now.next.next;
}
length--;
return deletedValue;
}
//转换为字符串方便显示
public String toString() {
StringBuilder sb = new StringBuilder("LinkedList: [");
for (Node now = head; now!=null; now=now.next) {
sb.append(now.value + ", ");
}
sb.append("]");
if (head != null)
sb.append("\n\t\t@ StartValue: " + head.value
+ "; TailValue: " + tail.value
+ "; Length: " + length);
return sb.toString();
}
//打印链表内容
void printSelf() {
System.out.println(this.toString());
}
//测试函数
static public void main(String[] argv) {
LinkedList list = new LinkedList();
list.addToHead(1);list.addToHead(2);list.addToHead(5);list.printSelf();
//list.deleteFromHead();list.deleteFromTail();list.printSelf();
list.addNode(12, 1);list.printSelf();
list.deleteNode(1);list.printSelf();
//System.out.println(list.contains(5));
//System.out.println(list.isEmpty());
}
}
//链表的结点
class Node{
int value; //节点的值
Node next; //下一个结点的指针
//两个构造函数
public Node(int value) {
this.value = value;
this.next = null;
}
public Node(int value, Node next) {
this.value = value;
this.next = next;
}
}