2 链表
数组是开辟一片连续空间存储,通过索引直接访问元素。
静态数组在初始化得知道元素数量,我们可以用动态数组,但是未能充分利用全部空间。
链表是由多个结点构成。
查找元素需要获得上一个结点引用。
private class Node
{
public E e; //结点存储的元素
public Node next; //下一个结点的引用(指针)
}
private Node head; //链表中头结点的引用
2.1 链表中添加结点
2.1.1 链表头部插入结点(头插法)
假设有以下链表
建立一个新结点,它的下一结点指向null
Node node = new Node(5);
把新结点的下一结点指向head结点
node.next = head;
更新头结点,head指向新结点
head = node;
完成往链表头部插入结点
2.1.2 往链表中间或尾部插入结点
假设往结点1后插入新结点6,找到结点1的下一结点指向6,6的下一结点指向结点2即可
使用Node类型的临时变量pre查找到所需结点1,此时pre的下一结点是2
Node pre = head;
for(int i = 0; i < index - 1; i++)
pre = pre.next;
新结点6的下一结点指向结点2(此时相当于指向pre的下一结点2)
Node node = new Node(6)
node.next = pre.next
pre的下一结点指向6
pre.next = node;
2.2 查询链表中的结点
利用临时变量cur
Node cur = head;
循环找到索引为3的结点
for(int i = 0; i < index; i++)
cur = cur.next;
2.3 删除链表中的结点
2.3.1 删除链表头部结点
删除结点5,只需把头结点指向结点5的下一结点
head = head.next
结点5没有引用会被回收。
2.3.2 删除链表中间或尾部的结点
假设要删除索引位置3的结点
临时变量pre找到要删除的结点的前一个结点
Node pre=head;
for(int i = 0; i < index - 1; i++)
pre = pre.next;
将索引3的结点6存入delNode,pre的下一结点指向delNode的下一结点
Node delNode=pre.next;
pre.next = delNode.next;
2.3.3 删除链表中指定的结点
假如删除结点6
临时变量cur结点指向head,临时pre结点指向null
当前结点的元素与要删除结点不同时,pre指向cur结点,cur指向下一个结点,直到cur找到对应元素结点
pre = cur;
cur = cur.next;
3.具体代码实现
using System;
using System.Collections.Generic;
using System.Text;
namespace LinkedList
{
class LinkedList1<E>//泛型链表类
{
private class Node//结点内部类
{
public E e;//存储的元素e
public Node next;//当前结点的下一个结点
public Node(E e,Node next)//构造函数初始化
{
this.e = e;
this.next = next;
}
public Node(E e)//没有下一结点的构造
{
this.e = e;
this.next = null;
}
public override string ToString()//打印
<