链表是由许多相同数据类型的元素按特定顺序排列而成的线性表,其特性时在计算机内存的位置是不连续与随机储存的,优点是数据的插入和删除都很方便,有新数据加入就向系统要一块内存空间,数据删除后就把空间还给系统,不需要移到大量数据,缺点是设计数据结构时比较麻烦,另外在查找数据时,也无法向静态数据一样可以随机读取数据,必须按顺序找到该数据为止。
1.建立单向列表
单向列表时所以列表中最常见的一种,就像它火车,所以节点串成一列,而且指针所指的方向一样。也就是列表中的每个数据除了要储存原本的数据,还必须储存下一个数据的储存位置,所以在程序设计语言中,一个列表节点有两个字段,即数据字段和链接字段,列表的组成基本要件为节点,而且每个节点不必储的存于连续的内存地址。
由于列表中的所有节点都知道节点本身的下一个节点在哪里,但是却没有办法知道前一个节点,所以“列表首”就特别重要,无论如何,只要列表首存在,就可以对整个列表进行遍历、加入和删除节点等操作,而之前建立的几点若没有串起来就会形成无人管理的节点,并一直占用内存空间。因此在建立列表时,必须有一列表指针指向列表首,并且除非必要否者不可移动列表首指针。
2.单向列表节点的插入
2.1在链表的第一个节点插入节点(头插法)
只需要把新节点的指针指向表头,再把表头移到新节点即可。
public void inserthead(int val) {
Entry entry = new Entry(val);
entry.next = head.next;
head.next = entry;
}
2.2在链表的最后一个节点插入节点(尾插法)
把列表的最后一个节点指向新节点,新节点再指向null即可。
public void insertTail(int val)
{
Entry cur = head;
while(cur.next!= null) //循环直到cur.next为空 把cur弹出
{
cur = cur.next;
}
cur.next = new Entry(val);//给cur.next 赋值为新节点的地址
}
2.3在链表的中间位置插入节点
如果插入的节点在X与Y之间,只要将X节点的指针指向新节点,新节点的指针指向Y节点即可。
以下是java插入节点的算法:
public void inster(int pos,int val) {
int i=0;
Entry cur = head;//获取头结点
while(cur.next != null) {
if(i == pos){
break;
}
i++;
cur = cur.next;
}
Entry entry = new Entry(val);
entry.next = cur.next;
cur.next = entry;
}
3.单向列表节点的删除
3.1删除列表的第一个节点
只要把列表指针指向第二个节点即可。
public void shanchead() {
head = head.next;
}
3.2删除列表的中间节点
只要将删除节点的前一个节点的指针,指向要删除的节点的下一个节点即可,
public void shanc(int val) {
Entry cur = head.next;
Entry pwd = head;
while(cur.next != null) {
if(cur.data == val) {
break;
}
cur = cur.next;
pwd = pwd.next;
}
pwd.next = cur.next;
}
3.2删除列表的最后一个节点
只要将指向最后一个节点的指针,指向null即可。
public void shanclast() {
Entry cur = head.next;
Entry pwd = head;
while(cur.next != null) {
cur = cur.next;
pwd = pwd.next;
}
pwd.next = null;
}
}
范例:
/*
* 单链表
*/
class Outer {
class Entry {
int data;
Entry next;
/**
* 头结点,空构造方法
*/
public Entry() {
data = 0;
next = null;
}
/**
* 构造节点
* @param a
*/
public Entry(int data) {
this.data = data;
next = null;
}
}
private Entry head = new Entry();//指向头结点的引用
/**
* 头插法
* @param val 需要插入的数据
*/
public void inserthead(int val) {
Entry entry = new Entry(val);
entry.next = head.next;
head.next = entry;
}
/**
* 尾插法
* @param val 需要插入的值
*/
public void insertlast(int val) {
Entry cur = head;
while(cur.next!= null) { //循环直到cur.next为空 把cur弹出
cur = cur.next;
}
cur.next = new Entry(val);//给cur.next 赋值为新节点的地址
}
/**
* 插入到pos位置 从有数据开始为0下标
* @param pos 位置序号
* @param val 插入的值
*/
public void inster(int pos,int val) {
int i=0;
Entry cur = head;//获取头结点
while(cur.next != null) {
if(i == pos){
break;
}
i++;
cur = cur.next;
}
Entry entry = new Entry(val);
entry.next = cur.next;
cur.next = entry;
}
/**
* 删除头节点
*/
public void shanchead() {
head = head.next;
}
/**
* 删除尾节点
*/
public void shanclast() {
Entry cur = head.next;
Entry pwd = head;
while(cur.next != null) {
cur = cur.next;
pwd = pwd.next;
}
pwd.next = null;
}
/**
* 删除指定元素
*/
public void shanc(int val) {
Entry cur = head.next;
Entry pwd = head;
while(cur.next != null) {
if(cur.data == val) {
break;
}
cur = cur.next;
pwd = pwd.next;
}
pwd.next = cur.next;
}
/*
* 反转链表
*/
public void back(){
Entry x = head.next;
Entry x1 = null;
Entry x2 = null;
while( x !=null) {
x1 = x.next;
x.next = x2;
x2 = x;
x = x1;
}
head.next = x2;
}
/**
* 获得链表长度
* @return 链表长度
*/
public int getlength() {
int i=0;
Entry cur = head;
while(cur.next != null) {
cur = cur.next;
i++;
}
return i;
}
/**
* 求倒数第K个元素
*
* @param k 序号
* @return 所求元素
*/
public int daok(int k) {
if(k<0 || k>getlength()-1) {
System.out.print("该下标不合法!");
return -1;
}
int x = getlength()-k;
int i=0;
Entry cur = head.next;
while(cur.next != null) {
if(x==i) {
break;
}
cur = cur.next;
i++;
}
return cur.data;
}
/**
* 遍历输出
*/
public void show() {
Entry cur = head.next;
while(cur != null) {
System.out.print(cur.data+" ");
cur = cur.next;
}
System.out.println();
}
}
public class DanLianBiao {
public static void main(String[] args) {
Outer s = new Outer();
/*头插法
*/
/*s.inserthead(25);
s.inserthead(35);
s.inserthead(36);
s.inserthead(68);
s.show();*/
/*尾插法
*/
s.insertlast(25);
s.insertlast(35);
s.insertlast(36);
s.insertlast(68);
s.show();
/* 删除元素
* */
/*s.shanchead();//删除头节点
s.show();
s.shanclast();//删除尾节点
s.show();*/
s.shanc(36);
s.show();
/*指定位置插入
*/
/*s.inster(0, 258);
s.inster(2, 368);
s.show();*/
/*倒数第k个元素
* */
/*System.out.println(s.daok(3));
System.out.println(s.daok(-1));*/
/*反转
*/
/*s.back();
s.show();*/
}
}
我和我舍友的名字和床号用单链表实现:
class OuterQuick {
class Entry {
int data;
String name;
Entry next;
public Entry() {
this.data = 0;
this.name = null;
this.next = null;
}
public Entry(String name,int data) {
this.data = data;
this.name = name;
this.next = null;
}
}
private Entry head = new Entry();
/**
* 头插法
* @param name 名字
* @param val 数据
*/
public void inserthead(String name,int data) {
Entry entry = new Entry(name,data);
entry.next = head.next;
head.next = entry;
}
/**
* 尾插法
* @param name 名字
* @param val 数据
*/
public void insertlast(String name,int data) {
Entry cur = head;
while(cur.next != null) {
cur = cur.next;
}
Entry entry = new Entry(name,data);
cur.next = entry;
}
/**
* 指定位置插入
* @param pos 指定的位置
* @param name 名字
* @param val 数据
*/
public boolean insert(int pos,String name,int data) {
if(pos < 0 ){
return false;
}
int i = 0;
Entry cur = head;
while(cur.next != null) {
if(i == pos) {
break;
}
cur = cur.next;
i++;
}
Entry entry = new Entry(name,data);
entry.next = cur.next;
cur.next = entry;
return true;
}
/**
*判空
*/
public boolean isEmpty() {
if(head.next == null) {
return true;
}
return false;
}
/**
* 删除元素
* @param key 要删除的数据
* @return
*/
public boolean delete(int key) {
if(isEmpty()) {
return false;
}
Entry cur = head;
Entry pwd = head.next;
while(pwd != null) {
if(pwd.data == key) {
break;
}
cur = cur.next;
pwd = pwd.next;
}
cur.next = pwd.next;
return true;
}
public void show() {
Entry cur = head;
while(cur.next != null) {
cur = cur.next;
System.out.println(cur.name+" "+cur.data);
}
}
}
public class LianXi{
public static void main(String[] args) {
OuterQuick s = new OuterQuick();
/*s.inserthead("李正全", 6);
s.inserthead("代云鹏",5);
s.inserthead("郭栋", 4);
s.inserthead("吴海波", 3);
s.inserthead("黄苗杰", 2);
s.inserthead("万琳琨", 1);*/
/*s.insertlast("万琳琨", 1);
s.insertlast("吴海波", 3);
s.insertlast("李正全", 6);
s.insertlast("郭栋", 4);
s.insertlast("黄苗杰", 2);
s.insertlast("代云鹏",5);*/
s.insert(0, "代云鹏",5);
s.insert(1, "郭栋", 4);
s.insert(2,"万琳琨", 1);
s.insert(3, "李正全", 6);
s.insert(4, "黄苗杰", 2);
s.insert(5, "吴海波", 3);
s.delete(5);
s.show();
}
}