数据结构算法基础 之 链表(单链表)
- 相较于数组,链表这个数据结构可能要复杂一些.
与数组相比 , 链表在内存上不是连续内存空间 , 是一些零散的内存块 , 通过指针来访问 .
这就要求链表的每一个节点都要有: 1. 指向下一个节点的指针. 2. 该节点可以存放的数据.
- java代码实现
/** * 链表节点 */ public class Node { int num; Node next; public Node(int num) { this.num = num; } }
/** * 链表: */ public class MyLinkList { int size; // 链表大小 Node head; // 头链表 // 初始化链表 public MyLinkList() { this.size = 0; this.head = null; } // 链表添加 从末尾添加 public boolean add(int num){ Node newNode = new Node(num); if(head == null){ head = newNode; size++; return true; } // 遍历链表 , 将新元素插入链表尾部 Node temp = head; while(temp.next != null){ temp = temp.next; } temp.next = newNode; size++; return true; } // 链表添加 从表头添加 public boolean addFromHead(int num){ Node temp = new Node(num); if(head == null){ head = temp; } temp.next = head; head = temp; size++; return true; } // 遍历打印链表 public void printLinkList(){ if(head == null){ System.out.println("null"); }else { Node temp = head; while(temp != null){ System.out.print(temp.num+" "); temp = temp.next; } System.out.println(); } } // 删除链表节点 指定位置 public boolean removeNode(int index){ if(head == null){ return false; } if(index < 1 || index > size){ return false; } if(index == 1){ head = head.next; size--; return true; } // 找到该节点的前节点 Node temp = head; Node nextTemp = head.next; // nextTemp最终为index出节点 temp最终为index节点的前节点 for(int i=1; i<index-1; i++){ temp = temp.next; nextTemp = nextTemp.next; } temp.next = nextTemp.next; size--; return true; } // 删除链表节点,指定节点数值 可能含多个 public boolean removeNodeByNum(int num){ // 如果从表头开始删除元素,遍历删除直到表头不是要删除的元素 while(head != null){ if(head.num == num){ head = head.next; size--; }else { break; } } // 判断链表是否为空 if(head == null){ return false; } // 遍历链表 表头不是要删除的元素,此时以nextTemp为基准 Node temp = head; Node nextTemp = head.next; while(nextTemp != null){ if(nextTemp.num == num){ temp.next = nextTemp.next; nextTemp = nextTemp.next; size--; continue; } temp = temp.next; nextTemp = nextTemp.next; } return true; } // 链表反转 public void reserve(){ if(head == null || head.next == null){ return; } Node pre = null; // 前结点 Node curNode = head; // 当前节点 Node nextNode = null; // 下个节点 while(curNode != null){ nextNode = curNode.next; curNode.next = pre; pre = curNode; curNode = nextNode; } head = pre; // 此时curNode已经为null了,最后的pre才是反转后链表的头节点 } // 去除重复元素 public void distinctLink(){ if(head == null || head.next == null){ return ; } Node temp = head; Node nextNode = head.next; Map map = new HashMap(16); map.put(temp.num,1); // 将头节点放入map中 while(nextNode != null){ if(!map.containsKey(nextNode.num)){ map.put(nextNode.num,1); }else{ // 如果包含了,删除该节点 temp.next = nextNode.next; size--; nextNode = nextNode.next; continue; } temp = temp.next; nextNode = nextNode.next; } } // 去除重复元素2 public void distinctLink2(){ Node curNode = head; Node preNode = null; Map map = new HashMap(8); while(curNode != null){ if(map.containsKey(curNode.num)){ // 如果包含 preNode.next = curNode.next; size--; }else { // 如果不包含 map.put(curNode.num,1); preNode = curNode; } curNode = curNode.next; } } // 节点排序 选择排序 public void sortLinkList(){ if(head ==null || head.next == null){ return; } Node curNode = head; while(curNode != null){ Node nextNode = curNode.next; while(nextNode != null){ if(curNode.num > nextNode.num){ int temp = curNode.num; curNode.num = nextNode.num; nextNode.num = temp; } nextNode = nextNode.next; } curNode = curNode.next; } } // 返回倒数第k个结点. 连个指针一个先走k-1步, 第二个指针开始走,当第一个到达尾节点时,第二个刚好到达倒数k个位置 public Node findReverNode(int k){ if(k < 0 || k > size){ return null; } Node firstNode = head; // 第一个指针 Node secondNode = head; // 第二个指针 // 第二个指针先走k-1步 for(int i = 0 ; i < k-1 ; i++){ secondNode = secondNode.next; } while(secondNode.next != null){ // 第一个指针开始 firstNode = firstNode.next; secondNode = secondNode.next; } return firstNode; } // 链表中间节点 快慢指针 public Node getMidNode(){ Node quickNode = head; Node slowNode = head; while(quickNode.next != null && quickNode.next.next != null){ quickNode = quickNode.next.next; slowNode = slowNode.next; } return slowNode; } // 链表中环的检测 public boolean isCross(){ Node quickNode = head; Node slowNode = head; while(quickNode.next != null && quickNode.next.next != null){ quickNode = quickNode.next.next; slowNode = slowNode.next; if(quickNode == slowNode){ return true; } } return false; } // 维护有序链表 public void addOrder(int num){ Node temp = new Node(num); if(head == null){ head = temp; size++; return ; } if(num < head.num){ temp.next = head; head = temp; size++; return; } Node curNode = head; Node preNode = null; while(curNode.next != null){ preNode = curNode; curNode = curNode.next; if(num < curNode.num){ preNode.next = temp; temp.next = curNode; size++; return; } } curNode.next = temp; size++; } // 两个有序的链表合并 public MyLinkList mergeLinkList(MyLinkList list1,MyLinkList list2){ Node temp = list2.head; while(temp != null){ list1.addOrder(temp.num); temp = temp.next; } return list1; } // 删除尾节点 public void removeEndNode(){ if(head == null){ return; } if(head.next == null){ head = null; size--; return; } Node curNode = head; Node nextNode = head.next; while(nextNode.next != null){ nextNode = nextNode.next; curNode = curNode.next; } curNode.next = null; size--; } }