大话数据结构 - 链表

2018-04-19  本文已影响102人  HikariCP

代码GitHub地址


链表概述

数组优缺点

说起链表必须说一下数组:数组是一种连续存储线性结构,元素类型相同,大小相等

数组优势:存取速度快。

数组劣势:

  1. 事先必须知道数组的长度
  2. 空间通常是有限制的
  3. 需要大块连续的内存块
  4. 插入删除元素的效率很低

链表优缺点

链表是离散存储线性结构

n个节点离散分配,彼此通过指针相连,每个节点只有一个前驱节点,每个节点只有一个后续节点,首节点没有前驱节点,尾节点没有后续节点。

链表优点:

  1. 空间没有限制
  2. 插入删除元素很快

链表缺点:

  1. 节点的获取很慢

链表分类

链表需要注意的点

解题步骤:

  1. 先考虑特殊情况,边缘值
  2. 进入退出循环时需要找准条件,考虑清楚退出循环时所需要的变量的终值是多少,方便使用
  3. 审视全局,带正确的值判断是否AC

控制选择的节点

int i = 1;

while (i < index) {
    headNode = headNode.getNextNode();
    i++;
}

这段代码意义即,从初始化i=0开始,如果要插入节点到第i个的位置。那么我们就一定需要找到第i-1个节点。所以现在我们目标明确了,要找第i-1个节点。
因为循环的结束条件是由i控制的,如果我们使变量i原本从0开始计数++到i-1结束。跳过的是i个元素。这样就把我们需要的第i-1节点跳过了。而我们要想取到它,很明显我们需要让循环少进行一次。
为了逻辑清晰,循环判断条件不应改变。那么我们就需要把i的初始值改为1,而非原先的0。

链表操作

目录:

Github - 单链表代码地址 - 欢迎star

添加数据到链表中

遍历链表

给定位置插入节点到链表中

    index = 3;
    ----
    int i = 0;
    temp = headNode.getNextNode();
    while(i < index){
        tempNode = tempNode.getNextNode();
        i++;
    }
    
    int i = 1;
    temp = headNode;
    while(i < index){
        tempNode = tempNode.getNextNode();
        i++;
    }

获取链表的长度

int i = 0;
tempNode = headNode.next;
while(tempNode!=null) {
    i++;
    tempNode = tempNode.next;
}

删除给定位置的节点

int i = 1;
while(i < 3){
    i++;
    temp = temp.next;
}

对链表进行排序

找到链表中倒数第k个节点

/**
     * 找链表倒数第index个节点
     *
     * @param headNode
     * @param index
     * @return
     */
    public static int findNode(Node headNode, int index) {
        int listLength = listLength(headNode);
        index = -index;
        int trueIndex = (index + listLength + 1) % listLength;
        for (int i = 0; i < trueIndex; i++) {
            headNode = headNode.getNextNode();
        }
        return headNode.getValue();
    }
/**
     * 找倒数第k个节点|追点,简洁写法
     *
     * @param headNode
     * @return
     */
    public static int findNode3(Node headNode, int k) {
        Node tempNode = headNode;
        Node nextNode = null;
        int i = 0;
        while (tempNode != null) {
            i++;
            tempNode = tempNode.getNextNode();
            if (tempNode == null) {
                break;
            }
            if (i == k) {
                nextNode = headNode.getNextNode();
            } else if (i > k) {
                nextNode = nextNode.getNextNode();
            }
        }
        return nextNode.getValue();
    }

删除链表重复数据

这里我用while循环写的,比较简单而且简洁。其实本质上和冒泡排序的思路一样,思考的时候用for循环的思路思考临界条件即可。非常简单

/**
 * 删除重复元素,|参考别人的 O(n2)
 *
 * @param headNode
 */
  public static void removeDumplecateEle(Node headNode) {
        Node temp = headNode.getNextNode();
        Node next;
        while (temp != null) {
            next = temp;
            while (next.getNextNode() != null) {
                if (next.getNextNode().getValue() == temp.getValue()) {
                    next.setNextNode(next.getNextNode().getNextNode());
                } else {
                    next = next.getNextNode();
                }
            }
            temp = temp.getNextNode();
        }
    }
/**
     * 删除重复元素 hashtable| 空间开销变大,O(n)
     *
     * @param headNode
     */
    public static void removeDuplecate3(Node headNode) {
        Hashtable<Integer, Integer> hashtable = new Hashtable<Integer, Integer>();
        Node tempNode = headNode.getNextNode();
        while (tempNode != null) {
            if (!hashtable.containsKey(tempNode.getValue())) {
                hashtable.put(tempNode.getValue(), 1);
            }
            tempNode = tempNode.getNextNode();
        }
        // 打印
        for (Map.Entry<Integer, Integer> entryItem : hashtable.entrySet()
                ) {
            System.out.println(entryItem.getKey());
        }
    }

查询链表的中间节点

递归从尾到头输出单链表

 /**
     * 链表逆序递归遍历
     *
     * @param headNode
     */
    public static void traverseByRecursive(Node headNode) {
        if (headNode != null) {
            traverseByRecursive(headNode.getNextNode());
            if (headNode.getValue() != HEAD_POINT_NUMBER) {
                System.out.println(headNode.getValue());
            }
        }
    }

反转链表

while (tempNode != null) {
       firstNode = tempNode;
       tempNode = tempNode.getNextNode();
       firstNode.setNextNode(nextNode);
       nextNode = firstNode;
}

单链表的扩展

都很简单,不赘述了。

上一篇 下一篇

猜你喜欢

热点阅读