包含头节点(head)的单链表的学习总结。 头结点是指不包含data,只包含指针的节点。
如有错误的地方,请大家不吝指正。
/**
* 包含头结点的单链表
* @author zsk
*
*/
public class MyList {
private Node head;//链表的头结点,只有指针,没有数据。
public MyList(){
this.head = new Node();
}
/** 头插法构建单链表
* 头插法可用于将链表逆序。
* @param data
*/
public void insertHead(int data){
Node node = new Node(data);
Node p = head.next;
head.next = null;
node.next = p;
head.next = node;
}
/** 尾插法构建单链表
* @param data
*/
public void insertTail(int data){
Node node = new Node(data);
Node tempHead = head.next;
Node tail = null;
if(tempHead==null){
tail = head;
}else{
while(tempHead!=null){
tail = tempHead;
tempHead = tempHead.next;
}
}
tail.next = node;
}
/**
* 判断链表是否为空
* @return
*/
public boolean isEmpty(){
return this.head.next==null?true:false;
}
/**
* 求链表的长度
* @return
*/
public int size(){
int size = 0;
Node node = head.next;
while(node!=null){
size++;
node = node.next;
}
return size;
}
/**
* 根据下标获取节点
* @param position
* @return
*/
public Node getNode(int position){
int pos = 0;
Node node = head.next;
if(position<0||position > size()){
try {
throw new Exception("下标越界");
} catch (Exception e) {
e.printStackTrace();
}
}else{
while(pos != position){
pos++;
node = node.next;
}
}
return node;
}
/**
* 为position位置上的节点设置新的值value
* @param position
* @param value
*/
public void set(int position,int value){
Node settedNode = getNode(position);
settedNode.setData(value);
}
/**
* 删除给定下标位置上的节点
* @param position
*/
public void delete(int position){
if(position<0||position>size()){
try {
throw new Exception("下标越界");
} catch (Exception e) {
e.printStackTrace();
}
}else{
if(position==0){
Node p = head.next;
Node q = p.next;
head.next = q;
p.next = null;
}else{
Node delPreNode = getNode(position-1);//被删除节点的前一个节点
Node delNode = getNode(position);
delPreNode.next = delNode.next;
delNode.next = null;
}
}
}
public void append(int position,Node node){
Node appendNode = getNode(position);
node.next = appendNode.next;
appendNode.next = node;
}
/**
* 使用头插法,将链表逆序
*/
public void revereList(){
if(this.size()>1){//至少有两个节点,再进行逆序
Node p = head.next;
head.next = null;
while(p!=null){
Node q = p.next;//记录下p节点的下一个节点
p.next = head.next;
head.next = p;
p = q;//让p节点指向它的下一个节点,重新判断是否需要循环
}
}
}
/**
* 使用递归,将链表逆序
*/
public void revereListByRecursion(){
Node first = head.next;
head.next = reverseListFun1(first);//将头结点的下一个节点设置为递归逆序后的第一个节点
}
/**
* 真正的递归方法,进行逆序
* @param head
* @return
*/
private Node reverseListFun1(Node head){//没有头结点的链表进行逆置(方法1:递归法)
Node p = head;
if(null == p)
return null;
Node q = p.next;
if(null == q)
return p;
else
head = reverseListFun1(q);//每次都是返回最后一个节点。
q.next = p; //|-- 这两步操作就只是将(锁)链表进行重新排序
p.next = null; //|--
return head;
}
/**
* 从前至后打印链表
* @param head
*/
public void printList(Node head){
Node tempHead = head.next;
while(tempHead!=null){
System.out.print(tempHead.data + ",");
tempHead = tempHead.next;
}
System.out.println();
}
/**
* 逆序输出链表的值(采用递归的方法)
* @param head
*/
public void reversePrintList(Node head){
/*if(head!=null){
reversePrintList(head.next);
System.out.print(head.data+",");
}*/
Node first = head.next;
reversPrint(first);
}
/**
* 对于无头结点的单链表使用的递归方法
* @param head
*/
private void reversPrint(Node head){
if(head!=null){
reversPrint(head.next);
System.out.print(head.data+",");
}
}
/**
* 获取链表的中间节点
* @param head
* @return
*/
public Node getMiddleNode(Node head){
if(null==head)//链表为空,则返回null
return null;
if(null==head.next||null==head.next.next)//链表只有一个节点或两个节点,则返回地一个节点
return head.next;
else{
Node p = head.next;
Node q = head.next;
while(q.next!=null){
q = q.next;
if(q!=null){
q = q.next;
}
if(q==null)
return p;
p = p.next;
}
return p;
}
}
/**
* 判断链表是否为循环链表
* @param head
* @return
*/
public boolean isCircle(Node head){
if(null==head)
return false;
if(null==head.next)
return false;
if(null==head.next.next)
return false;
Node p = head.next;
Node q = head.next;
while(true){
p = p.next;
q = q.next;
if(q==null||p==null)
return false;
q = q.next;//如果q!=null则q再向后移一格。
if(q==null)
return false;
if(p==q)
return true;
}
}
/**
*
* 合并两个有序List
* @param list1
* @param list2
* @return
*/
public static Node mergeList(MyList list1,MyList list2){
MyList result = new MyList();
int i = 0;
int j = 0;
while(i<list1.size()&&j<list2.size()){
Node list1_node = list1.getNode(i);
Node list2_node = list2.getNode(j);
if(list1_node.data<list2_node.data){
result.insertTail(list1_node.data);
i++;
}
else{
result.insertTail(list2_node.data);
j++;
}
}
while(i<list1.size()){
result.insertTail(list1.getNode(i).data);
i++;
}
while(j<list2.size()){
result.insertTail(list2.getNode(j).data);
j++;
}
return result.head;
}
public static class Node{
private int data;
private Node next;
public Node(){}
public Node(int data){
this.data = data;
this.next = null;
}
public int getData(){
return this.data;
}
public void setData(int data){
this.data = data;
}
}
public static void main(String[] args){
MyList myList = new MyList();
int[] a = {3,1,2,6,3,8,0};
for(int i=0;i<a.length;i++){
myList.insertHead(a[i]);
// myList.insertTail(a[i]);
}
System.out.println("是否为空:" + myList.isEmpty());
System.out.println("链表长度:" + myList.size());
myList.printList(myList.head);
myList.revereListByRecursion();
System.out.println("逆序后输出:" );
myList.printList(myList.head);
System.out.println("逆序后下标为3的位置上的值为:" + myList.getNode(3).data);
System.out.println("逆序后下标为5的位置上的值为:" + myList.getNode(5).data);
// System.out.println("逆序后下标为5的位置上的值为:" + myList.get(8));
myList.set(5, 99);
System.out.println("修改值后链表输出:");
myList.printList(myList.head);
myList.delete(5);
System.out.println("删除下标为5的节点后,链表输出:");
myList.printList(myList.head);
myList.delete(0);
System.out.println("删除下标为0的节点后,链表输出:");
myList.printList(myList.head);
System.out.println("在下标为0点节点后插入一个值为78的节点后,链表输出:");
Node node = new Node(78);//需要将内部类声明为static,否则会有如下的编译错误。因为main函数是静态的,静态只能访问静态。
//No enclosing instance of type MyList is accessible.
//Must qualify the allocation with an enclosing instance of type MyList
//(e.g. x.new A() where x is an instance of MyList).
myList.append(0, node);
myList.printList(myList.head);
MyList myList1 = new MyList();
int[] a1 = {1,2,3,4,6};
for(int i=0;i<a1.length;i++){
myList1.insertTail(a1[i]);
}
MyList myList2 = new MyList();
int[] a2 = {1,4,6,8,9};
for(int i=0;i<a2.length;i++){
myList2.insertTail(a2[i]);
}
Node headNode = MyList.mergeList(myList1, myList2);
System.out.println("");
myList.printList(headNode);
}
}