如何从尾到头输出单链表

package linklist;

import org.junit.Test;

import java.util.Hashtable;

/**
 * 明白头指针与头结点的区别:
 * 头结点,放在第一个元素结点之前,其数据域一般无意义(存放链表长度)
 * 头指针:链表中指向第一个结点的指针
 * @author kankan
 * @creater 2019-06-01 7:56
 */
public class LinkedList {
    int size;//链表节点的个数
    Node head = null;//链表头的引用
    /**
     * 头插法
     */
    public int addNodeHead(int data){
        Node newNode = new Node(data);//1.生成新结点
        if (0 == size){//2.判断是否是头结点
            head = newNode;
        }else{
            newNode.next = head;
            head = newNode;//让头指针指向第一个结点
        }
        size++;
        return data;
    }
    // 注意这里 index 从 0 开始
    public int addNodeIndex(int index,int data) {
        if (index < 0 || index > size) {
            System.out.println("角标越界!");
            return -1;
        }
        if (index == 0) {
            return addNodeHead(data);//头插法
        } else if (index == size) {
            return addNodeTail(data);//尾插法
        } else {
            Node pre = head;
            Node cur = head.next;
            //
            while (pre != null && index > 1) {
                pre = pre.next;
                cur = cur.next;
                index--;
            }
            //循环结束后 pre 保存的是索引的上一个节点 而 cur 保存的是索引值当前的节点
            Node node = new Node(data);

            node.next = cur;
            pre.next = node;
            size++;
        }
        return data;
    }

    /**
     * 向链表中插入数据
     * 尾插法
     * 每次的新结点都插在终端结点的后面
     */
    public int addNodeTail(int data){
        Node newNode = new Node(data);//1.生成新结点
        if (0 == size){//2.判断头指针指向第一个是否为null
            head = newNode;
        }else{
            //3.遍历到终点
            Node tmp = head;
            while (tmp.next != null){
                tmp = tmp.next;
            }
            tmp.next = newNode;//4.遍历到终端结点,进行插入
        }
        size++;
        return data;
    }
    //在链表头删除元素
    public boolean deleteHead(){
        if (null == head) {
            System.out.println("当前链表为空!");
            return false;
        }
        int obj = head.data;
        head = head.next;
        size--;
        return true;
    }
    /**
     * 删除第index个结点
     * 第一个结点的存储位置称为头指针
     */
    public boolean deleteNode(int index){
        if (index < 0 || index >= size){
            System.out.println("下标越界或小于0");
            return false;
        }
        //删除链表第一个元素
        if (0 == index){
            head = head.next;
            size--;
            return true;
        }
        int i = 1;
        Node pre= head;
        Node cur = pre.next;
        while (cur != null){
            if (i == index){
                pre.next = cur.next;
                size--;
                return true;
            }
            pre = cur;
            cur = cur.next;
            i++;
        }
        return true;
    }
    //尾删除法
    public boolean deleteTail(){
        if (null == head) {
            System.out.println("当前链表为空!");
            return false;
        }
        if (1 == size){
            head = null;
        }else{
            Node deleteNode = head;
            //找到倒数第二个不指向null结点,因为我们删除倒数第一个结点
            while (deleteNode.next != null && deleteNode.next.next != null) {
                deleteNode = deleteNode.next;
            }
            deleteNode.next = null;//倒数第二个结点的next赋null
        }
        size--;
        return true;
    }
    //显示节点信息
    public void display(){
        if(size > 0){
            Node node = head;
            int tempSize = size;
            if(tempSize == 1){//当前链表只有一个节点
                System.out.println("["+node.data+"]");
                return;
            }
            while(tempSize>0){
                if(node.equals(head)){
                    System.out.print("["+node.data+"->");
                }else if(node.next == null){
                    System.out.print(node.data+"]");
                }else{
                    System.out.print(node.data+"->");
                }
                node = node.next;
                tempSize--;
            }
            System.out.println();
        }else{//如果链表一个节点都没有,直接打印[]
            System.out.println("[]");
        }
    }

    /**
     * 选择排序
     * 返回排序后的头结点
     * @param args
     */
    public Node orderList(){
        Node nextNode = null;
        int temp = 0;
        Node curNode = head;
        while(curNode.next != null){
            nextNode = curNode.next;
            while (nextNode != null){
                //数据从小到大
                if (curNode.data > nextNode.data){
                    temp = curNode.data;
                    curNode.data = nextNode.data;
                    nextNode.data = temp;
                }
                nextNode = nextNode.next;
            }
            curNode = curNode.next;
        }
        return head;
    }

    //从链表中删除重复数据

    /**
     * 遍历链表,将链表中的数据存储到HashTable中,若当前遍历的数据在HashTable中存在,说明这个数据重复,可以将这个数据删除掉
     * @param head
     */
    public void deleteDuplecate(Node head){
        if (null == head){
            System.out.println("链表为空");
            return;
        }
        Hashtable<Integer,Integer> table = new Hashtable<Integer, Integer>();
        Node tmp = head;
        Node pre = null;
        while (tmp != null){
            //当前访问的值,在hashtable中存在
            if (table.containsKey(tmp.data)){
                //若当前遍历的数据在HashTable中存在,说明这个数据重复,可以将这个数据删除掉
                pre.next = tmp.next;
                size--;
            }else{//不包含此值,把这个键值对插入
                table.put(tmp.data,1);
                pre = tmp;
            }
            tmp = tmp.next;
        }
    }
    //从链表中删除重复数据
    /**
     * 对链表进行双重循环遍历,
     * 外层循环正常遍历链表,若当前遍历到的结点为curNode
     * 内层循环从curNode.next开始遍历,若碰到与curNode结点的值相同的结点,删除掉这个重复的结点
     * @param head
     */
    public void deleteDuplecate1(Node head){
        if (null == head){
            System.out.println("链表为空");
            return;
        }
        Node curNode = head;
        while (curNode != null){
            Node insideNode = curNode;
            while (insideNode.next != null){
                if (curNode.data == insideNode.next.data){
                    insideNode.next = insideNode.next.next;
                    size--;
                }else{
                    insideNode = insideNode.next;
                }
            }
            curNode = curNode.next;
        }
    }
    //如何找出单链表中的倒数第k个元素
    public Node findElem(Node head,int k){
        if (k < 1){
            return null;
        }
        Node p1 = head;
        Node p2 = head;
        //开始时候让快慢指针相差k个结点
        //前移k-1步
        for (int i = 0; i < k - 1 && p1 != null; i++) {
            p1 = p1.next;
        }
        if (p1 == null){
            System.out.println("k大于size");
            return null;
        }
        //由于开始时候让快慢指针相差k个结点
        //然后同时往前移动到快指针先行指针为null,
        //令一个指针所指的位置就是我们想要的
        while (p1.next != null){
            p1 = p1.next;
            p2 = p2.next;
        }
        return p2;
    }
    //如何实现链表的反转
    public static Node ReverseIteratively(Node head){
        Node pre = null;
        Node next = null;
        while (head != null) {
            next = head.next;
            head.next = pre;
            pre = head;
            head = next;
        }
        return pre;
    }
    //递归实质上就是系统帮你压栈的过程,系统在压栈的时候会保留现场
    public Node reverse(Node head) {
        //递归
        if (null == head ||null  == head.next)
            return head;
        Node temp = head.next;
        Node newHead = reverse(head.next);
        temp.next = head;
        head.next = null;
        return newHead;
    }
    //从尾到头输出单链表
    public void printListReverse(Node node){
        if (node != null){
            printListReverse(node.next);
            System.out.println(node.data);
        }
    }
    @Test
    public void testCase() {
        LinkedList list = new LinkedList();
        System.out.println("测试头插法");
        list.addNodeHead(4);
        list.addNodeHead(3);
        list.addNodeHead(2);
        list.addNodeHead(1);
        list.display();
        System.out.println("从头到尾输出单链表");
        list.printListReverse(list.head);
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值