有唯一一个被称为第一个和最后一个的数据元素
除第一个,所有元素有且仅有一个前驱;除最后一个,所有元素有且仅有一个后继
1.顺序存储结构
地址连续的存储单元
可随机存储(用下标访问)
2.链式存储结构
任意的存储单元
链表
结点:数据域+指针域,最后一个结点指针域为null
3.链表的类型
静态链表:用数组描述的链表
循环链表:最后一个结点的指针域指向头结点
双向链表:每个结点有两个指针域
1.在单链表中插入一个结点
需要从头遍历单链表,知道找到要插入的位置,修改next指针,完成插入
2.O(1)删除单链表中的指定的结点
将指定节点之后的所有内容复制到此处
3.逆向输出单链表的各个结点的值
利用栈
4.输出单链表倒数第k个结点的值
两个指针,一个指针先行k步,当先行指针到达单链表的末尾时,后行指针指向的节点就是所求
public ListNode FindKthToTail(ListNode head,int k) { //求链表倒数第k和节点,两个指着指向原链表的头结点,先让一个指针前进k-1步,此时,两个指针同时前进,当先行指针到达结尾时,后行指针即所求 if(head == null){ return null; } if(k == 0){ return null; } ListNode before = head; ListNode after = head; for(int i=1;i<=k-1;i++){ before = before.next; } if(before == null){ //链表的总长度都没有k个 return null; } while(before.next!=null){ before = before.next; after = after.next; } return after; }
5.输出单链表的中间节点
两个指针,一个指针一次走两步,一个指针一次走一步,快的指针到达链表末尾时,慢的指针就是所求
6.判断单链表是否有环
两个指针,一个指针一次走两步,一个指针一次走一步,如果中途慢的指针追上了快的指针,证明有环
7.反转链表
public ListNode ReverseList(ListNode head) { ListNode pre = null; ListNode cur = head; while(cur != null){ ListNode next = cur.next; cur.next = pre; pre = cur; cur = next; } if(pre != null){ return pre; }else{ return cur; } }
8.合并链表
那个链表的头结点小,那个链表就是合并之后链表的头结点
public ListNode Merge(ListNode list1,ListNode list2) { if(list1==null && list2!=null){ return list2; } if(list1!=null && list2==null){ return list1; } if(list1==null && list2==null){ return null; } if(list1.val<=list2.val){ return merge(list1, list2); }else{ return merge(list2, list1); } } public ListNode merge(ListNode list1,ListNode list2){ //永远list1的第一个结点都是小于list2的第一个结点 ListNode head = list1; ListNode temp1 = head.next; ListNode temp2 = list2; while(temp1!=null &&temp2!=null){ if(temp1.val<=temp2.val){ head.next = temp1; head = head.next; temp1 = temp1.next; }else{ head.next = temp2; head = head.next; temp2 = temp2.next; } } if(temp1 != null){ head.next = temp1; } if(temp2 != null){ head.next = temp2; } return list1; }