链表知识点总结

package 链表;

/**

 * 定义一个结点

 * @author LiZhe

 *

 */

class Node{

        Node next = null;

        int data;

        public Node(int data){

                this.data = data;

        }

}

/**

 * 链表

 * @author LiZhe

 *

 */

public class MyLinkedList {

        Node head = null;//链表的头结点

        /**

         * 添加结点

         * @param data

         */

        public void addNode(int data){

//将数据封装到结点中,即创建新结点

Node newNode = new Node(data);

//如果链表是空链表,将新结点添加给头结点

if(head == null){

head = newNode;

return;

}

//如果链表是非空链表,将新节点添加到链表末尾处

Node tmp = head;

while(tmp.next != null){

tmp = tmp.next;

}

tmp.next = newNode;

        }

/**

 * 删除第index个结点

 * @param index

 * @return

 */

public boolean deleteNodeByIndex(int index){

//角标不合理

if(index<1 || index>length()){

return false;

}

//index==1的情况

if(index == 1){

head = head.next;

return true;

}

//index大于等于2的情况

int i = 2;

Node preNode = head;

Node curNode = preNode.next;

while(curNode != null){

if(index == i){

preNode.next = curNode.next;

return true;

}

preNode = curNode;

curNode = curNode.next;

i++;

}

return true;

}

/**

 * 对链表进行排序,并返回排序后的头结点

 *

 * 思路:用选择排序的思想对链表排序。第一个结点和第二个结点相比较,小的往前放,第一个结点和第三个结点相比较,

 *小的往前放...,第一次排序后,最小值放在第一个结点处。将第一个结点的下一个结点重新设为第一个结点,重复上述过程。

 * @return

 */

public Node orderList(){

Node curNode = head;

while(curNode.next != null){

Node nextNode = curNode.next;

while(nextNode !=null){

if(curNode.data>nextNode.data){

int temp = curNode.data;

curNode.data = nextNode.data;

nextNode.data = temp;

}

nextNode = nextNode.next;

}

curNode = curNode.next;

}

return head;

}

/**

 * 从链表中删除重复数据

 *

 * 思路:对链表进行双重遍历,外循环正常遍历链表,假设外循环当前遍历的结点为cur,内循环从cur.next开始遍历,若碰到与cur

 * 结点里存的数据值相同,则删除这个重复结点。

 */

public void deleteDuplecate(){

Node curNode = head;

while(curNode != null){

Node preNode = curNode;

Node nextNode = curNode.next;

while(nextNode != null){

if(curNode.data == nextNode.data){

preNode.next = nextNode.next;

nextNode=nextNode.next;

}else{

preNode = nextNode;

nextNode=nextNode.next;

}

}

curNode = curNode.next;

}

}

/**

 * 如何从尾到头打印链表

 *

 * 思路:要实现反过来打印链表,每访问到一个结点,先递归输出它后面的结点,再输出该结点自身

 */

public void printListReversely(Node head){

Node tmp = head;

if(tmp != null){

printListReversely(tmp.next);

System.out.println(tmp.data);

}

}

/**

 * 反转链表

 *

 * 思路:从头到尾遍历原链表,在断开当前结点与下一个结点的联系之前,先保存当前节点的下一个结点,然后,让当前结点指向上一个结点,将当前结点定义为新的上一个结点,将当前结点的下一个结点定义为新的当前结点。直到当前节点的下一个结点为null时,将当前结点定义反转后链表的头结点。

 *

 * @param head

 */

public void reverseList(){

if(head == null || head.next == null){

return;

}

Node current = head;//定义当前结点,初始值为头结点head

Node preCurrent = null;//定义当前节点的上一个结点,初始值为null

Node reverseHead = head;//定义反转后链表的头结点,初始值为未反转前链表的头结点

while(current != null){

Node next = current.next;//在断开当前结点与下一个结点联系之前,保存当前节点的下一个结点

//如果当前结点的下一个结点为null,那么当前结点就是反转后的链表的头结点

if(next == null)

reverseHead = current;

current.next = preCurrent;//断开当前结点与下一个结点的联系,让当前结点指向上一个结点

preCurrent = current;//将当前结点定义为新的上一个结点

current = next;//将当前结点的下一个结点定义为新的当前结点

}

this.head = reverseHead;

}

/**

 * 如何寻找单链表的中间结点

 *

 * 思路:第一步:定义快、慢两个指针,两个指针均从头开始遍历;

 *          第二步:快指针一次走两步,慢指针一次走一步;

 *          第三步:当快指针走到链表尾部时,慢指针恰好到达链表中部

 *

 * @param head

 * @return

 */

public Node searchMidNode(Node head){

Node p = head;

Node q = head;

while(p!=null && p.next!=null && p.next.next!=null){

p = p.next.next;

q = q.next;

}

return q;

}

/**

 * 如何检测一个单链表是否有环

 *

 * 思路:定义两个指针fast和slow,快指针一次走两步,慢指针一次走一步,快指针每移动一次都要跟慢指针比较,直到当快指针等于慢指针时,说明这个链表是

 * 带环的单向链表,否则,说明这个链表不是带环的单向链表。

 *

 * @param head

 * @return

 */

public boolean hasCycle(Node head){

if(head == null){

return false;

}

Node fast = head;

Node slow = head;

while(fast!=null && fast.next!=null){

slow = slow.next;

fast = fast.next.next;

if(slow == fast){

return true;

}

}

return false;

}

/**

 * 如何判断两个链表是否相交

 *

 * 思路:如果两个链表相交,那么它们一定有着相同的尾结点,因此实现思路为:分别遍历两个链表,记录它们的尾结点,如果

 * 它们的尾结点相同,那么说明这两个链表相交,否则不想交。

 *

 * @param head1

 * @param head2

 * @return

 */

public boolean isIntersect(Node head1,Node head2){

if(head1==null || head2==null){

return false;

}

//找出第一个链表的尾结点

Node tail1 = head1;

while(tail1.next != null){

tail1 = tail1.next;

}

//找出第二个链表的尾结点

Node tail2 = head2;

while(tail2.next != null){

tail2 = tail2.next;

}

return tail1 == tail2;

}

/**

 * 打印链表

 */

public void printList(){

Node tmp = head;

while(tmp!=null){

System.out.println(tmp.data);

tmp = tmp.next;

}

}

/**

 * 计算链表长度

 * @return

 */

public int length(){

int length = 0;

Node tmp = head;

while(tmp != null){

length++;

tmp = tmp.next;

}

return length;

}

/**

 * 主函数

 * @param args

 */

public static void main(String[] args) {

MyLinkedList myLinkedList = new MyLinkedList();

myLinkedList.addNode(1);

myLinkedList.addNode(9);

myLinkedList.addNode(3);

myLinkedList.addNode(6);

myLinkedList.addNode(7);

System.out.println("打印链表:");

myLinkedList.printList();

}

}

猜你喜欢

转载自blog.csdn.net/lz1170063911/article/details/80092378