risc-v中文社区

 找回密码
 立即注册
查看: 1300|回复: 4

[原创] 自制java双链

  [复制链接]

5

主题

8

帖子

49

积分

新手上路

Rank: 1

积分
49
发表于 2021-7-31 16:48:27 | 显示全部楼层 |阅读模式
有时候,数组排序(有重复数据),同时还需要原始序号,网上有很多办法,我写了一个通用的双链(当然是与我们的需要原始序号要关联的双链):
import java.util.*;
import java.util.stream.Collectors;
class Student implements Comparable<Student> {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public int compareTo(Student o) {
        if(age == o.age) {
            return name.compareTo(o.name);
        }
        else {
            return age - o.age;
        }
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

class Unit implements Comparable<Student>{
    private int index;
    private Student student;

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {
        this.student = student;
    }

    @Override
    public int compareTo(Student o) {
        return student.compareTo(o);
    }

    public Unit(int index, Student student) {
        this.index = index;
        this.student = student;
    }
}
class Node<T> {
    public Node pre;
    public T data;
    public Node next;
}

回复

使用道具 举报

5

主题

8

帖子

49

积分

新手上路

Rank: 1

积分
49
 楼主| 发表于 2021-7-31 16:50:28 | 显示全部楼层
public class ArraySort {
    public static void main(String[] args)
    {
        int[] data1 =  { 4,2,6,8,1,0,2,6,5,4,1};
        Arrays.sort(data1);
        for (int i:data1 ) {
            System.out.println(i);
        }
        //上面是一个默认的简单的数组排序,可以看出,值相同的排在一起了,如果除了要排序之外,还需要获得对应的序号怎么办???针对这种情况,我写了本实验代码,当有了本代码之后,再做排序取序号将会很容易

        //如果使用了java8的新特性,比如stream则有可能性能不是很好,还是要从最基础的java语法角度来处理可能性能更高些

        Student[] studentsraw = { new Student("zs", 10),new Student("lisi",11),new Student("wangwu", 9),
                new Student("zs", 10),new Student("lisi",11),new Student("wangwu", 9),
                new Student("zs", 10),new Student("lisi",11),new Student("wangwu", 9),
                new Student("zs", 10),new Student("lisi",11),new Student("wangwu", 9)};
        int index = 0;
        for (Student s:studentsraw ) {
            Unit unit = new Unit(index++,s);
            append(unit);
        }
        List<Unit> all = getall();
        for (Unit u:all ) {
            System.out.println(u.getIndex()+" : " + u.getStudent().getName() +"--->"+u.getStudent().getAge());
        }

    }

    private static int size;
    private static Node<Node<Unit>> nodeHead ,nodeTail;
    private static void append(Unit unit) {
        if(nodeHead == null) {
            nodeHead = new Node<>();
            Node<Unit> data = new Node<>();
            data.data = unit;
            nodeHead.data = data;
            nodeTail = nodeHead;
            size++;
            return;
        }
        //查整个node有没有这个数据
        Node<Unit> ret = searchnNodeReturData(unit);
        if(ret == null) {
            //说明没有这个数据 nodetail之后放入
            Node<Node<Unit>> newNode = new Node<>();
            Node<Unit> newdata = new Node<>();
            newdata.data = unit;
            newNode.data = newdata;
            newNode.pre = nodeTail; //新node的pre指向原nodetail
            nodeTail.next = newNode; //原nodetail的next指向新node
            nodeTail = newNode;//让nodeTail始终指向最后一个node
        }
        else {
            //说明有这个数据,需要放入DATA双链中
            Node<Unit> newdata = new Node<>();
            newdata.data = unit;
            Node<Unit> tmpdata = ret;
            while(true) {
                if(ret.next == null){
                    ret.next = newdata;//最后一个node的next要指向新数据
                    newdata.pre = ret;//新数据的pre要指向原最后一个node
                    break;
                }
                ret = ret.next;
            }
        }
        size++;
    }

    /**
     * 将所有的Unit全部返回
     * @return
     */
    private static List<Unit> getall() {
        if(nodeHead==null)
            return null;
        List<Unit> unitList = new ArrayList<>();
        for(Node<Node<Unit>> tmp = nodeHead;tmp != null;tmp = tmp.next) {
            for(Node<Unit> tmpdata = tmp.data; tmpdata != null; tmpdata = tmpdata.next) {
                unitList.add(tmpdata.data);
            }
        }
        return unitList;
    }
    private static List<Unit> getFirst() {
        if(nodeHead==null)
            return null;
        List<Unit> firstList = new ArrayList<>();
        for(Node<Unit> data = nodeHead.data;data != null;data = data.next) {
            firstList.add(data.data);
        }
        return firstList;
    }
    private static List<Unit> getLast() {
        if(nodeTail == null)
            return null;
        List<Unit> lastList = new ArrayList<>();
        for(Node<Unit> data = nodeTail.data;data != null;data = data.next) {
            lastList.add(data.data);
        }
        return lastList;
    }

    private static int deleunitdata(Unit unit) { //有可能有相同值的数据,只有unit中除了数据之外还有index,所以参数只能是unit
        //index和realdata都相同的则删除
        if((nodeHead==null) || (nodeHead.data == null) || (unit == null)) //表示是空链或unit为空
            return -1;
        int offset = 0;
        for(Node<Node<Unit>> tmphead = nodeHead;tmphead != null;tmphead = tmphead.next) {
            if(tmphead.data.data.compareTo(unit.getStudent()) == 0) {
                offset = 0;
                for(Node<Unit> tmpdata = tmphead.data; tmpdata != null; tmpdata = tmpdata.next) {
                    if(tmpdata.data.getIndex() == unit.getIndex()) { //还要判断index是否相同
                        if(offset == 0) { //头部  nodeTail要不要考虑???
                            Node<Node<Unit>> pre = tmphead.pre;
                            Node<Node<Unit>> next = tmphead.next;
                            if(tmpdata.next == null) { //只有这一个节点,没有重复的数据 ,本Node<Node<Unit>>删除掉,调整双链相关指针
                                if((tmphead.data.data.getIndex() == nodeTail.data.data.getIndex()) &&
                                        (tmphead.data.data.getStudent().compareTo(nodeTail.data.data.getStudent()) == 0)){
                                    pre.next= next;//next此时就是null
                                    nodeTail = pre;//nodeTail要前移
                                }
                                else {
                                    pre.next= next;
                                    next.pre = pre;
                                }

                            }
                            else { //有多个节点的重复数据
                                Node<Unit> newdatanode = tmpdata.next; //不可能是空即尾部
                                newdatanode.pre = null;//由原来的pre变成null,因为现在为首部了
                                Node<Node<Unit>> curNode = new Node<>();
                                curNode.data = newdatanode;
                                if((tmphead.data.data.getIndex() == nodeTail.data.data.getIndex()) &&
                                        (tmphead.data.data.getStudent().compareTo(nodeTail.data.data.getStudent()) == 0)){
                                    nodeTail = curNode; //nodeTail调整为新节点
                                    pre.next = curNode;
                                    curNode.pre = pre;
                                }
                                else {
                                    //下面四句让双链指针再次建立联系
                                    pre.next = curNode;//指向删除的节点,现在要指向新创建的节点
                                    curNode.pre = pre;
                                    curNode.next = next;//新节点的next指向被删除节点的next
                                    next.pre = curNode;
                                }
                            }
                        }
                        else { //找到节点时不是头部,是中间的某个节点 不用考虑nodeTail
                            Node<Unit> pre = tmpdata.pre;
                            Node<Unit> next = tmpdata.next;
                            pre.next = next;
                            if(tmpdata.next != null) { //不是最后一个
                                next.pre = pre;
                            }
                        }
                        return 0;
                    }
                    offset++;
                }
            }
        }
        return -1;
    }
    /**
     * 查找某个node的data中的数据数量,0表示空,返回值表示下次插入数据的"offset",也就是当前data中数据的数量
     * @param data 每个node的data其实是一个双向链表,只存head,所以调用此函数时data参数必须是node的data也就是双链的head
     * @return
     */
    private static int getDataLastPosition(Node<Unit> data) { //数据值都是相同的,只是找一个位置而已
        if((data==null) || (data.data == null)) //表示是空链 或unit为空
            return 0;
        int position = 0;
        do {
            position++;
            data = data.next;
        }while (data.next != null);
        return position;
    }

    /**
     * 在node中查找数据,找到则返回node的data节点即重复数据双向链的头,没找到则返回null
     * @param unit
     * @return
     */
    private static Node<Unit> searchnNodeReturData(Unit unit) { //java方法重载不能以返回值类型来区分
        if((nodeHead==null) || (nodeHead.data == null) || (unit == null)) //表示是空链或unit为空
            return null;
        for(Node<Node<Unit>> tmphead = nodeHead;tmphead != null;tmphead = tmphead.next) {
            if(tmphead.data.data.compareTo(unit.getStudent()) == 0)
                return tmphead.data;
        }
        return null;
    }

    /**
     * 查找整个Node中是否有数据unit,找到则返回true,没找到返回false
     * @param unit
     * @return
     */
    private static boolean searchNode(Unit unit) {
        if((unit == null) || (nodeHead == null)) {
            return false;
        }
        for(Node<Node<Unit>> tmphead = nodeHead;tmphead != null;tmphead = tmphead.next) {
            if(tmphead.data.data.compareTo(unit.getStudent()) == 0)
                return true;
        }
        return false;
    }
}

回复

使用道具 举报

5

主题

8

帖子

49

积分

新手上路

Rank: 1

积分
49
 楼主| 发表于 2021-7-31 16:51:13 | 显示全部楼层
显示如下:
0
1
1
2
2
4
4
5
6
6
8
0 : zs--->10
3 : zs--->10
6 : zs--->10
9 : zs--->10
1 : lisi--->11
4 : lisi--->11
7 : lisi--->11
10 : lisi--->11
2 : wangwu--->9
5 : wangwu--->9
8 : wangwu--->9
11 : wangwu--->9
回复

使用道具 举报

347

主题

564

帖子

2237

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2237
发表于 2021-7-31 17:02:10 | 显示全部楼层
好帖,值得学习!
回复

使用道具 举报

347

主题

564

帖子

2237

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2237
发表于 2021-7-31 17:05:05 | 显示全部楼层
越看有有意思!下次以这个代码做个risc-v java小应用APP。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



Archiver|手机版|小黑屋|risc-v中文社区

GMT+8, 2024-4-27 15:07 , Processed in 0.015563 second(s), 17 queries .

risc-v中文社区论坛 官方网站

Copyright © 2018-2021, risc-v open source

快速回复 返回顶部 返回列表