9.11 begin 数结(单向链表最佳实现)
常见面试题:
- 字符串模式匹配(KMP)
- 汉诺塔(分治)
- 八皇后(回溯)
- 马踏棋盘(图的深度优先+贪心算法)
课程目标:掌握本质,能达到在工作中灵活运用解决实际问题和优化程序。
程序 = 数据结构 + 算法
数据结构分类:
- 线性结构
- 非线性结构
Today 的第一个code为 Java单链表
在写链表之前,我们来讨论一下什么是引用,因为这挺重要的。
是指创建一个对象并把这个对象赋给一个引用变量。
在内存上申请一块内存,一个变量object引用它。
Object object = new Object();
·如果没有实现构造函数,系统会默认加上一个无参数的构造函数。·
package LinkedList;
/**
* 我定义的单向链表,其中第一个元素index为1
*
* @param <T>
*/
public class MyLinkedList<T> {
private Node<T> head;
private Node<T> tail;
private int size; //仅仅记录链表长度,不做规定
private class Node<T>{
private T data;
private Node<T> next;
public Node() {
data = null;
next = null;
}
public Node(T data) {
this.data = data;
next = null;
}
@Override
public String toString() {
return "Node{" +
"data=" + data +
", next=" + next +
'}';
}
}
public int getSize(){
return this.size;
}
//构造函数
public MyLinkedList(){
this.head = null;
this.tail = null;
this.size = 0;
}
public T getFirst() throws Exception{
rangeCheck();
return this.head.data;
}
private void rangeCheck() throws Exception {
if (isEmpty()) {
throw new Exception("List is empty");
}
}
private void indexCheck(int index) throws Exception{
if (index>this.size || index<=0){
throw new IllegalArgumentException("Illegal Index");
}
}
public T getLast() throws Exception{
rangeCheck();
return this.tail.data;
}
public Boolean isEmpty(){
return this.size == 0;
}
public Boolean isNotEmpty(){
return !isEmpty();
}
/**
我定义第一个节点就为头节点,最后一个节点为size大小,index 从一开始
*/
public T getAt(int index) throws Exception{
return (T) getNodeAt(index).data;
}
/**
* 根据Node中的data查找在表中的位序
* @param data
*/
public int getIndexAt(T data) throws Exception{
int index = 1;
rangeCheck();
Node<T> tmp = this.head;
while(tmp!=null && tmp.data!=data){
tmp = tmp.next;
index++;
}
if (tmp==null) return -1;
else return index;
}
public Node getNodeAt(int index) throws Exception{
rangeCheck();
indexCheck(index);
Node<T> temp = this.head;
for (int i = 1; i <=index-1 ; i++) {
temp = temp.next; // 这段代码多多理解。temp = 一个内存地址
}
return temp;
}
/**
* 尾插法
* @param data
*/
public void addLast(T data){
// create
Node<T> node = new Node();
node.data = data;
// attach
if (isNotEmpty()) {
this.tail.next = node;
}
if (isEmpty()){
this.head = node;
}
this.tail = node;
this.size +=1;
}
/**
* 头插法
* @param data
*/
public void addFirst(T data){
Node<T> node = new Node();
node.data = data;
if (isNotEmpty()){
node.next = head;
}
if (isEmpty()){
this.tail = node;
}
this.head = node;
this.size +=1;
}
/**
* 假如idx=1,那么头插,如果idx>siz,尾插
* @param data
* @param idx
*/
public void addAt(T data,int idx) throws Exception{
if (idx<=0){
throw new IllegalArgumentException("Illegal Index");
}
if (idx == 1){
addFirst(data);
}else if(idx>size){
addLast(data);
}
Node<T> node = new Node();
node.data = data;
Node preNode = getNodeAt(idx-1);
node.next = preNode.next;
preNode.next = node;
}
public T removeFirst() throws Exception{
rangeCheck();
Node<T> tmp = this.head;
if (this.size ==1 ){
this.head = null;
this.tail = null;
this.size =0;
}else {
head = head.next;
this.size--;
}
return tmp.data;
}
public T removeLast() throws Exception{
rangeCheck();
if (this.size ==1 ){
this.head = null;
this.tail = null;
this.size =0;
}
Node<T> tmp = this.tail;
Node preNode = getNodeAt(this.size-1);
preNode.next = null;
this.tail = preNode;
this.size--;
return tmp.data;
}
public T removeAt(int idx) throws Exception{
rangeCheck();
indexCheck(idx);
if (idx == 1){
removeFirst();
}else if(idx ==this.size){
removeLast();
}
Node<T> prefix = getNodeAt(idx - 1);
Node<T> removeNode = prefix.next;
prefix.next = removeNode.next;
this.size --;
return removeNode.data;
}
public void removeAll() throws Exception {
while (this.size>0){
removeFirst();
}
}
public void display(){
System.out.println("========================");
Node temp = this.head;
while(temp!=null){
System.out.println(temp.data);
temp = temp.next;
}
System.out.println("Over");
}
}