/**
* Created by zejian on 2016/10/23.
* 双链表的实现,带头结点(不带数据)的双链表,为了更高的效率该类包含指向尾部的指针tail
*/
public class HeadDoubleILinkedList<T> implements ILinkedList<T> {
protected DNode<T> head; //不带数据的头结点
protected DNode<T> tail; //指向尾部的指针
public HeadDoubleILinkedList(){
//初始化头结点
this.head =this.tail= new DNode<>();
}
//先省略其他代码
........
}
package com.zejian.structures.LinkedList.doubleLinked;
/**
* Created by zejian on 2016/10/23.
* 双链表结点
*/
public class DNode<T> {
public T data;
public DNode<T> prev, next;//前继指针和后继指针
public DNode(T data, DNode<T> prev, DNode<T> next)
{
this.data = data;
this.prev = prev;
this.next = next;
}
public DNode(T data)
{
this(data, null, null);
}
public DNode()
{
this(null, null, null);
}
public String toString()
{
return this.data.toString();
}
}
/**
* 插入结点
* @param index
* @param data
* @return
*/
@Override
public boolean add(int index, T data) {
if(index<0||data==null)
throw new NullPointerException("index < 0 || data == null");
int j = 0;
DNode<T> front = this.head;
//查找要插入结点位置的前一个结点
while (front.next != null && j < index) {
j++;
front = front.next;
}
//创建需要插入的结点,并让其前继指针指向front,后继指针指向front.next
DNode<T> q = new DNode<T>(data, front, front.next);
//空双链表插入和尾部插入,无需此操作
if(front.next != null) {
//更改front.next的前继指针
front.next.prev = q;
}
//更改front的后继指针
front.next = q;
//在尾部插入时需要注意更新tail指向
if(front==this.tail){
this.tail=q;
}
return true;
}
/**
* 根据下标删除结点
* 1.头删除
* 2.中间删除
* 3.尾部删除,更新tail指向
* @param index 下标起始值为0
* @return
*/
@Override
public T remove(int index) {
int size=length();
T temp=null;
if(index<0||index>=size||isEmpty()){
return temp;
}
DNode<T> p=this.head;
int j=0;
//头删除/尾删除/中间删除,查找需要删除的结点(要删除的当前结点因此i<=index)
while (p!=null&&j<=index){
p=p.next;
j++;
}
//当双链表只有一个结点时或尾部删除时,无需此步
if(p.next!=null){
p.next.prev=p.prev;
}
p.prev.next=p.next;
//如果是尾结点
if (p==this.tail) {
this.tail = p.prev;//更新未结点的指向
}
temp=p.data;
return temp;
}
@Override
public T get(int index) {
if (index>=0)
{
int j=0;
//注意起始结点为this.head.next
//如果起始点为this.head时,j的判断为j<=index,
//因为需要寻找的是当前结点而不是前一个结点。
DNode<T> pre=this.head.next;
while (pre!=null && j<index)
{
j++;
pre=pre.next;
}
if (pre!=null)
return pre.data;
}
return null;
}
@Override
public T set(int index, T data) {
T old=null;
if (index>0&&data!=null){
int j=0;
DNode<T> pre =this.head.next;
//查找需要替换的位置
while (pre!=null&&j<index){
j++;
pre=pre.next;
}
if (pre!=null){
old=pre.data;
//替换数据
pre.data=data;
}
}
return old;
}
package com.zejian.structures.LinkedList.doubleLinked;
import com.zejian.structures.LinkedList.ILinkedList;
/**
* Created by zejian on 2016/10/23.
* 双链表的实现,带头结点(不带数据)的双链表,为了更高的效率该类包含指向尾部的指针tail
*/
public class HeadDoubleILinkedList<T> implements ILinkedList<T> {
protected DNode<T> head; //不带数据的头结点
protected DNode<T> tail; //指向尾部的指针
public HeadDoubleILinkedList(){
this.head =this.tail= new DNode<>(); //初始化头结点
}
/**
* 传入一个数组,转换成链表
* @param array
*/
public HeadDoubleILinkedList(T[] array)
{
this();
if (array!=null && array.length>0)
{
this.head.next = new DNode<T>(array[0]);
tail =this.head.next;
tail.prev=this.head;
int i=1;
while (i<array.length)
{
tail.next=new DNode<T>(array[i++]);
tail.next.prev=tail;
tail = tail.next;
}
}
}
@Override
public boolean isEmpty() {
return head.next==null;
}
@Override
public int length() {
int length=0;
DNode<T> pre=head.next;
while (pre!=null){
length++;
pre=pre.next;
}
return length;
}
@Override
public T get(int index) {
if (index>=0)
{
int j=0;
DNode<T> pre=this.head.next;
while (pre!=null && j<index)
{
j++;
pre=pre.next;
}
if (pre!=null)
return pre.data;
}
return null;
}
@Override
public T set(int index, T data) {
T old=null;
if (index>0&&data!=null){
int j=0;
DNode<T> pre =this.head.next;
//查找需要替换的位置
while (pre!=null&&j<index){
j++;
pre=pre.next;
}
if (pre!=null){
old=pre.data;
//替换数据
pre.data=data;
}
}
return old;
}
/**
* 插入结点
* @param index
* @param data
* @return
*/
@Override
public boolean add(int index, T data) {
if(index<0||data==null)
throw new NullPointerException("index < 0 || data == null");
int j = 0;
DNode<T> front = this.head;
//查找要插入结点位置的前一个结点
while (front.next != null && j < index) {
j++;
front = front.next;
}
//创建需要插入的结点,并让其前继指针指向front,后继指针指向front.next
DNode<T> q = new DNode<T>(data, front, front.next);
//空双链表插入,需要确保front.next不为空
if(front.next != null) {
//更改front.next的前继指针
front.next.prev = q;
}
//更改front的后继指针
front.next = q;
//在尾部插入时需要注意更新tail指向
if(front==this.tail){
this.tail=q;
}
return true;
}
/**
* 尾部添加
* @param data
* @return
*/
@Override
public boolean add(T data) {
if (data==null)
return false;
//创建新结点,并把其前继指针指向tail
DNode<T> q = new DNode<T>(data, tail, null);
tail.next=q;
//更新尾部结点
this.tail=q;
return true;
}
/**
* 根据下标删除结点
* 1.头删除
* 2.中间删除
* 3.尾部删除,更新tail指向
* @param index 下标起始值为0
* @return
*/
@Override
public T remove(int index) {
int size=length();
T temp=null;
if(index<0||index>=size||isEmpty()){
return temp;
}
DNode<T> p=this.head;
int j=0;
//头删除/尾删除/中间删除,查找需要删除的结点(要删除的当前结点因此i<=index)
while (p!=null&&j<=index){
p=p.next;
j++;
}
//当链表只要一个结点时,无需此步
if(p.next!=null){
p.next.prev=p.prev;
}
p.prev.next=p.next;
//如果是尾结点
if (p==this.tail) {
this.tail = p.prev;//更新未结点的指向
}
temp=p.data;
return temp;
}
/**
* 根据data删除结点,无需像单向链表那样去存储要删除结点的前一个结点
* 1.头删除
* 2.中间删除
* 3.尾部删除,更新tail指向
* @param data
* @return
*/
@Override
public boolean removeAll(T data) {
boolean isRemove=false;
if(data==null||isEmpty())
return isRemove;
//注意这里的起点,如果起点为this.head,那么情况区别如同前面的根据index的删除实现
DNode<T> p=this.head.next;
//头删除/尾删除/中间删除(size>1),查找所有需要删除的结点
while (p!=null){
if(data.equals(p.data)){
if (p==this.tail){
//如果是尾结点
this.tail=p.prev;//更新未结点的指向
p.prev=null;
this.tail.next=null;
}else {
//如果是在中间删除,更新前继和后继指针指向
p.prev.next=p.next;
p.next.prev=p.prev;
}
isRemove=true;
p=p.next;//继续查找
}else {
p=p.next;
}
}
return isRemove;
}
/**
* 清空链表
*/
@Override
public void clear() {
this.head.next=null;
this.tail=this.head;
}
@Override
public boolean contains(T data) {
if(data==null){
return false;
}
DNode<T> p=this.head.next;
while (p!=null){
if (data.equals(p.data)){
return true;
}else {
p=p.next;
}
}
return false;
}
@Override
public String toString() {
String str="(";
DNode<T> pre = this.head.next;
while (pre!=null)
{
str += pre.data;
pre = pre.next;
if (pre!=null)
str += ", ";
}
return str+")";
}
public static void main(String[] args){
String[] letters={"A","B","C","D","Z","E","F"};
// String[] letters={"A"};
HeadDoubleILinkedList<String> list=new HeadDoubleILinkedList<>(letters);
System.out.println("list.get(3)->"+list.get(3));
System.out.println("list:"+list.toString());
System.out.println("list.add(4,Y)—>"+list.add(0,"Y"));
System.out.println("list:"+list.toString());
System.out.println("list.add(Z)—>"+list.add("Z"));
System.out.println("list:"+list.toString());
System.out.println("list.contains(Z)->"+list.contains("Z"));
System.out.println("list.set(4,P)-->"+list.set(4,"P"));
System.out.println("list:"+list.toString());
System.out.println("list.remove(6)-->"+list.remove(6));
// System.out.println("list.remove(Z)->"+list.removeAll("Z"));
System.out.println("list:"+list.toString());
}
}
/**
* 根据index插入
* 循环链表中无论是prev还是next都不存在空的情况,因此添加时
* 无论是头部还是尾部还是中,都视为一种情况对待
* @param index
* @param data
* @return
*/
@Override
public boolean add(int index, T data) {
int size=length();
if(data==null||index<0||index>=size)
return false;
int j=0;
DNode<T> p=this.head;
//寻找插入点的位置
while (p.next!=head&&j<index){
p=p.next;
j++;
}
//创建新结点,如果index=3,那么插入的位置就是第4个位置
DNode<T> q=new DNode<>(data,p,p.next);
p.next=q;
p.next.prev=q;
return true;
}
@Override
public T remove(int index) {
T old = null;
int size=length();
if (index<0||index>=size)
return old;
int j=0;
DNode<T> p=this.head.next;
while (p!=head && j<index)
{
j++;
p = p.next;
}
if (p!=head)
{
old = p.data;
p.prev.next = p.next;
p.next.prev = p.prev;
}
return old;
}
package com.zejian.structures.LinkedList.doubleLinked;
import com.zejian.structures.LinkedList.ILinkedList;
/**
* Created by zejian on 2016/10/24.
* 循环双链表,带空头结点(不含数据),循环链表可以不需要尾部指针
*/
public class LoopHeadDILinkedList<T> implements ILinkedList<T> {
protected DNode<T> head; //不带数据的头结点
// protected DNode<T> tail; //指向尾部的指针
public LoopHeadDILinkedList(){
this.head = new DNode<>();//初始化头结点
this.head.next=head;
this.head.prev=head;
}
/**
* 传入一个数组,转换成链表
* @param array
*/
public LoopHeadDILinkedList(T[] array)
{
this();
if (array!=null && array.length>0)
{
DNode<T> p= new DNode<>(array[0]);
head.next=p;
head.prev=p;
p.prev=head;
p.next=head;
int i=1;
while (i<array.length)
{
p.next=new DNode<>(array[i++],p,head);
head.prev=p.next;
p=p.next;
}
}
}
@Override
public boolean isEmpty() {
return this.head.next==head;//循环双链表的后继指针指向自己说明是空链表
}
@Override
public int length() {
int length=0;
DNode<T> p=this.head.next;
while (p!=this.head){
length++;
p=p.next;
}
return length;
}
@Override
public T get(int index) {
if (index>=0)
{
int j=0;
DNode<T> p=this.head.next;
while (p!=head && j<index)
{
j++;
p=p.next;
}
if (p!=head)
return p.data;
}
return null;
}
/**
* 根据index修改data
* @param index
* @param data
* @return 返回被替换的data
*/
@Override
public T set(int index, T data) {
if (data==null){
return null;
}
if(index>=0){
int j=0;
DNode<T> p=this.head.next;
while (p!=head&&j<index){
j++;
p=p.next;
}
//如果不是头结点
if(p!=head){
T old = p.data;
p.data=data;
return old;
}
}
return null;
}
/**
* 根据index添加
* 循环链表中无论是prev还是next都不存在空的情况,因此添加时
* 无论是头部还是尾部还是中,都视为一种情况对待
* @param index
* @param data
* @return
*/
@Override
public boolean add(int index, T data) {
int size=length();
if(data==null||index<0||index>=size)
return false;
int j=0;
DNode<T> p=this.head;
//寻找插入点的位置
while (p.next!=head&&j<index){
p=p.next;
j++;
}
//创建新结点,如果index=3,那么插入的位置就是第4个位置
DNode<T> q=new DNode<>(data,p,p.next);
p.next=q;
p.next.prev=q;
return true;
}
/**
* 尾部添加
* @param data
* @return
*/
@Override
public boolean add(T data) {
if(data==null)
return false;
//创建新结点,让前继指针指向head.pre,后继指针指向head
DNode<T> p=new DNode<>(data,head.prev,head);
//更新tail后继指针的指向
this.head.prev.next=p;
this.head.prev=p;
return true;
}
@Override
public T remove(int index) {
T old = null;
int size=length();
if (index<0||index>=size)
return old;
int j=0;
DNode<T> p=this.head.next;
while (p!=head && j<index)
{
j++;
p = p.next;
}
if (p!=head)
{
old = p.data;
p.prev.next = p.next;
p.next.prev = p.prev;
}
return old;
}
@Override
public boolean removeAll(T data) {
boolean isRemove=false;
if(data==null){
return isRemove;
}
DNode<T> p=this.head.next;
while (p!=head){
if(data.equals(p.data)){
p.prev.next=p.next;
p.next.prev=p.prev;
isRemove=true;
}
p=p.next;
}
return isRemove;
}
@Override
public void clear() {
this.head.prev = head;
this.head.next = head;
}
@Override
public boolean contains(T data) {
if (data==null){
return false;
}
DNode<T> p=this.head.next;
while (p!=head){
if(data.equals(p.data)){
return false;
}
p=p.next;
}
return false;
}
@Override
public String toString()
{
String str="(";
DNode<T> p = this.head.next;
while (p!=head)
{
str += p.data.toString();
p = p.next;
if (p!=head)
str += ", ";
}
return str+")";
}
public static void main(String[] args){
String[] letters={"A","B","C","D","Z","E","F"};
LoopHeadDILinkedList<String> list=new LoopHeadDILinkedList<>(letters);
System.out.println("init list-->"+list.toString());
System.out.println("list.get(3)->"+list.get(3));
System.out.println("list:"+list.toString());
System.out.println("list.add(4,Y)—>"+list.add(4,"Y"));
System.out.println("list:"+list.toString());
System.out.println("list.add(Z)—>"+list.add("Z"));
System.out.println("list:"+list.toString());
System.out.println("list.contains(Z)->"+list.contains("Z"));
System.out.println("list.set(4,P)-->"+list.set(4,"P"));
System.out.println("list:"+list.toString());
System.out.println("list.remove(3)-->"+list.remove(3));
System.out.println("list.remove(Z)->"+list.removeAll("Z"));
System.out.println("list:"+list.toString());
}
}
package com.zejian.structures.LinkedList.doubleLinked;
/**
* Created by zejian on 2016/11/6.
* 升序排序链表,继承LoopHeadDILinkedList
*/
public class SortLoopHeadDIlinkedList<T extends Comparable<? extends T>> extends LoopHeadDILinkedList<T> {
/**
* 顺序插入
* @param data
* @return
*/
@Override
public boolean add(T data) {
if(data==null||!(data instanceof Comparable))
throw new NullPointerException("data can\'t be null or data instanceof Comparable must be true");
Comparable cmp =data;//这里需要转一下类型,否则idea编辑器上检验不通过.
//如果data值比最后一个结点大,那么直接调用父类方法,在尾部添加.
if(this.isEmpty() || cmp.compareTo(this.head.prev.data) > 0){
return super.add(data);
}
DNode<T> p=this.head.next;
//查找插入点
while (p!=head&&cmp.compareTo(p.data)>0)
p=p.next;
DNode<T> q=new DNode<>(data,p.prev,p);
p.prev.next=q;
p.prev=q;
return true;
}
public static void main(String[] args){
SortLoopHeadDIlinkedList<Integer> list=new SortLoopHeadDIlinkedList<>();
list.add(50);
list.add(40);
list.add(80);
list.add(20);
System.out.println("init list-->"+list.toString());
}
}
| 传递参数 | 链表 | 动态数组 |
|---|---|---|
| 索引 | O(n) | O(1) |
| 在最前端插入或删除 | O(1) | O(n) |
| 在最末端插入 | O(n) | O(1),如果数组空间没有被填满;O(n),如果数组空间已填满 |
| 在最末端删除 | O(n) | O(1) |
| 在中间插入 | O(n) | O(n) |
| 在中间删除 | O(n) | O(n) |
| 空间浪费 | O(n) | O(n) |
package com.zejian.structures.LinkedList.XORLinked;
/**
* Created by zejian on 2016/11/6.
* 异或结点
*/
public class XORNode<T> {
public T data;
public XORNode<T> ptrdiff;//异或指针
public XORNode() {
}
public XORNode(T data, XORNode<T> ptrdiff) {
this.data = data;
this.ptrdiff = ptrdiff;
}
}
(B ♁ D) ♁ D = B ♁(D ♁ D) = B ♁ 0 =B
(B ♁ D) ♁ B = D ♁(B ♁ B) =B ♁ 0 = D
机械节能产品生产企业官网模板...
大气智能家居家具装修装饰类企业通用网站模板...
礼品公司网站模板
宽屏简约大气婚纱摄影影楼模板...
蓝白WAP手机综合医院类整站源码(独立后台)...苏ICP备2024110244号-2 苏公网安备32050702011978号 增值电信业务经营许可证编号:苏B2-20251499 | Copyright 2018 - 2025 源码网商城 (www.ymwmall.com) 版权所有