数据结构-------单链表

单链表:

在计算机科学中,链表是数据元素的线性组合,元素储存上并不连续

可以分为:单向链表双向链表循环链表

 单向链表:

首先,定义结点的类型,它包括和下一个结点。

头部插入法:

相关java代码:

 1 private  Node head;//定义头部结点
 2     public class Node{
 3         private int value;//每个结点的值
 4         private Node next;//指向下一个结点
 5         public Node(int value,Node next) {
 6             this.value=value;
 7             this.next=next;
 8         }
 9     }
10     //实现添加元素的方法
11     public void addFirwst(int value) {
12 //        head = new Node(value,null) ;//假设链表为空,也就是head为空   这一行代码和下一行代码功能一样    head为空那么new Node(value,head)
13         head = new Node(value,head);//假设链表不为空  赋值完成之后作为头部节点
14     }
15     //while循环遍历元素loop
16     public  void loop1() {
17         Node p = head;
18         while(p!=null) {
19             System.out.print(p.value+"\t");
20             p=p.next;
21         }
22     }

相关测试代码:

1 SingleLinkList singlelinklist = new SingleLinkList();
2         singlelinklist.addFirwst(6);
3         singlelinklist.addFirwst(2);
4         singlelinklist.addFirwst(8);
5         singlelinklist.addFirwst(12);
6         singlelinklist.addFirwst(0);
7         System.out.println("遍历元素loop1:");
8         singlelinklist.loop1();

结果显示:每次添加元素   添加的顺序为 6  12  8  2  6存放到链表中,由此可见,每次添加元素头添加元素(头插法),并将新的结点作为头节点

各种遍历方法:

除了上述代码中的while循环还有for循环和迭代器和Consumer等方法,方法改变了条件不变作为遍历的条件。

//for循环遍历元素
    public void loop2() {
        for(Node p=head;p!=null;p=p.next) {
            System.out.print(p.value+"\t");
        }
    }
    //通过Consumer来遍历元素
    public void loop3(Consumer<Integer> consumer) {
        for(Node p=head;p!=null;p=p.next) {
            consumer.accept(p.value);
        }
    }
    //通过迭代器来遍历元素
    @Override
    public Iterator<Integer> iterator() {
        // TODO Auto-generated method stub
        return new Iterator<Integer>() {
            Node p =head;
            @Override
            public boolean hasNext() {
                // TODO Auto-generated method stub
                return p!=null;
            }

            @Override
            public Integer next() {
                // TODO Auto-generated method stub
                int value = p.value;
                p=p.next;
                return value;
            }
        };
    }

尾部插入法:

尾部插入法,首先要找到最后一个元素,只有找到最后一个元素,才能够往后面添加元素。

 1 //尾插法   尾部插入   主要找到尾部最后一个元素
 2     private Node findLast() {
 3         if(head==null) {
 4             return null;
 5         }
 6         Node p;
 7         for(p=head;p.next!=null;p=p.next) {
 8             
 9         }
10         return p;
11     }
12     public void addLast(int value) {
13         Node last = findLast();//找到最后一个元素
14         if(last==null) {
15             addFirwst(value);
16             return;
17         }
18         last.next = new Node(value,null);
19     }

相关测试代码:

1 singlelinklist.addLast(22);
2         singlelinklist.addLast(18);
3         singlelinklist.addLast(6);
4         singlelinklist.addLast(8);
5         singlelinklist.addLast(2);
6         for(Integer value:singlelinklist) {//迭代方式遍历
7             System.out.print(value+"\t");
8         }

效果如下,由此可见尾插法遍历和插入的顺序一致,头部插入顺序和遍历顺序相反

根据索引值求返回值:

根据索引来找到元素:参数[传入索引]  记录每次元素的索引值,但不保存下来,保存下来会消耗大量的空间

 1 //根据索引求返回值
 2     private Node findNode(int index) {
 3         int i=0;
 4         Node p;
 5         for(p=head;p!=null;p=p.next,i++) {
 6             if(i==index) {
 7                 return p;
 8             }
 9         }
10         return null;
11     }
12     public int get(int index) {
13         Node p = findNode(index);
14         if(p==null) {
15             throw new IllegalArgumentException(String.format("index [%d] 不合法", index));
16         }
17         return p.value;
18     }

相关结果测试

 1 //测试获取某个值  
 2         int a = singlelinklist.get(0);
 3         int b = singlelinklist.get(1);
 4         int c = singlelinklist.get(2);
 5         int d = singlelinklist.get(3);
 6         int e = singlelinklist.get(4);
 7         
 8         
 9         System.out.println();
10         System.out.println("获取下标元素值:a="+a+"\t\tb="+b+"\tc="+c+"\td="+d+"\te="+e);
11         int f = singlelinklist.get(5);
12         System.out.println("f="+f);

结果显示:

根据索引值添加元素:

添加元素,你要知道上一个元素和下一个元素

 1 //给出索引添加元素
 2     public void insert(int index,int value) {
 3         if(index==0) {
 4             addFirwst(value);
 5             return;
 6         }
 7         Node prev = findNode(index-1);//找到当前元素的前一个元素
 8         if(prev==null) {
 9             throw new IllegalArgumentException(String.format("index [%d] 不合法", index));
10         }
11         prev.next = new Node(value,prev.next);//new Node(value,prev.next)  中的prev.next为下一个元素的值
12         
13     }

相关测试代码:

//按照索引添加元素
        System.out.println("\n添加元素:");
        singlelinklist.insert(1, 20);
        for(Integer value:singlelinklist) {
            System.out.print(value+"\t");
        }

结果显示,根据索引添加元素值。

删除第一个元素:

1 //删除第一个元素
2     public void removeFirst() {
3         if(head==null) {
4             throw new IllegalArgumentException(String.format("index [%d] 不合法"));
5         }
6         head = head.next;
7     }

相关测试代码:

1     System.out.println("\n删除元素:");
2         singlelinklist.removeFirst();
3         for(Integer value:singlelinklist) {
4             System.out.print(value+"\t");
5         }

结果显示:

根据索引删除元素:

 1 //根据索引删除元素
 2     public void remove(int index) {
 3         //根据index-1前面一个元素
 4         if(index==0) {
 5             removeFirst();
 6         }
 7         Node prev = findNode(index-1);
 8         if(prev==null) {
 9             throw new IllegalArgumentException(String.format("index [%d] 不合法"));
10         }
11         Node removed = prev.next;
12         if(removed==null) {
13             throw new IllegalArgumentException(String.format("index [%d] 不合法"));
14         }
15         prev.next = removed.next;
16         
17     }

 根据索引,删除值,这个时候需要考虑的东西比较多,如果你要删除第一个元素和上面removeFirst()方法一样,如果这个列表只有一个元素也需要考虑。

posted on 2024-01-14 12:31  无名之辈的ggb  阅读(4)  评论(0编辑  收藏  举报