链表(上)
来源:互联网 发布:px4数据更新 编辑:程序博客网 时间:2024/06/07 08:10
链表作为最进本的数据结构,在程序设计中有着非常重要的作用,其存储特点如下:可以用任意一组存储单元来存储单链表中的数据元素(存储单元可以是不连续的),而且,除了存储每个数据元素的值以外,还必须存储指示其直接后继元素的信息,这两部分信息组成的数据元素的存储映像称为结点。N个结点链在一块被称为链表,当结点只包含其后继结点的信息的链表就被称为单链表。
单链表有带头结点和不带头结点之分:
不带头结点
带头结点
eg1:基本操作
先定义如下数据类来存储结点信息
public class Node { Node next=null; int data; public Node(){}; public Node(int data){ this.data=data; }}
package linkedlist;public class MyLinkedList { Node head=null;//链表头,不带头结点 public void addNode(int d){//向链表中插入数据 Node newNode=new Node(d); if(head==null){ head=newNode; return; } Node tmp=head; while(tmp.next!=null){ tmp=tmp.next; } tmp.next=newNode; } public Boolean deleteNode(int index){//删除第index个结点 if(index<1||index>length()){ return false; } if(index==1){ head=head.next; return true; } int i=2; Node preNode=head; Node curNode=preNode.next; while(curNode!=null){ if(i==index){ preNode.next=curNode.next; return true; } preNode=curNode; curNode=curNode.next; i++; } return true; } public int length(){//返回长度 int length=0; Node tmp=head; while(tmp!=null){//tmp.next!=null不一样 length++; tmp=tmp.next; } return length; } public Node orderList(){//对链表进行排序,返回排序后的头结点 Node nextNode=null; //选择排序 int temp=0; Node curNode=head; while(curNode!=null){ nextNode=curNode.next; while(nextNode!=null){//第一个和剩下的进行比较获得min if(curNode.data>nextNode.data){ temp=curNode.data; curNode.data=nextNode.data; nextNode.data=temp; } nextNode=nextNode.next; } curNode=curNode.next; } return head; } public void printList(){ Node tmp=head; while(tmp!=null){ System.out.println(tmp.data); tmp=tmp.next; } } public static void main(String [] args){ MyLinkedList list=new MyLinkedList(); list.addNode(3); list.addNode(1); list.addNode(5); list.addNode(3); list.printList(); System.out.println(list.length()); list.deleteNode(1);//数的是个数,删除第一个,不是索引0 System.out.println("listLen="+list.length()); System.out.print("before order:"); list.printList(); list.orderList(); System.out.print("after order:"); list.printList(); }}
eg2:从链表中删除重复数据
package linkedlist;import java.util.*;/* * 从链表中删除重复数据 */public class DeleteDuplecate { /* * 遍历链表,把遍历到的值存储到一个Hashtable中,在遍历过程中,若当前访问的值 * 在Hashtable中已经存在,说明这个数据是重复的,可以删除 * 时间复杂度低,但是在遍历过程中需要额外的存储空间来保存已遍历过的值 */ public static void deleteDuplecate(Node head){ Hashtable<Integer,Integer> table=new Hashtable<Integer,Integer>(); Node tmp=head; Node pre=null; while(tmp!=null){ if(table.containsKey(tmp.data)){ pre.next=tmp.next; } else{ table.put(tmp.data, 1); pre=tmp; } tmp=tmp.next; } } /* * 双重循环遍历,外循环正常遍历链表 * 假设外循环当前遍历的结点为cur,内循环从cur开始遍历,若碰到与cur所指向结点值相同 * 则删除这个重复结点 * 不需要额外的存储空间,但时间复杂度比上面高 */ public static void deleteduplecate(Node head){ Node p=head; while(p!=null){ Node q=p; while(q.next!=null){ if(p.data==q.next.data){ q.next=q.next.next; } else{ q=q.next; } } p=p.next; } } public static void print(Node head){ while(head!=null){ System.out.print(head.data+" "); head=head.next; } System.out.println(); } public static void main(String[] args){ int[] num={2,4,3,3,5}; Node head=new Node(); Node pre=head; for(int i=0;i<num.length;i++){ Node node=new Node(num[i]); pre.next =node; pre=node; } print(head.next); deleteduplecate(head);// deleteDuplecate(head); print(head.next); }}
eg3:找出单链表中倒数第k个元素
package linkedlist;/* * 找出单链表中倒数第k个元素 * 方法一:先遍历一边单链表,求出长度n,然后将倒数第k个转为正数n-k个 * 再遍历一次即可得到,问题,需要对链表进行两次遍历 * 方法二: * 设置两个指针,其中一个比另一个先前移k-1步,然后两个指针同时前移 * 先行的指针值为null时另一个指针所指的位置就是要找的位置 */public class FindElem { public static Node findElem(Node head, int k){ if(k<1){ return null; } Node p1=head; Node p2=head; for(int i=0;(i<k-1 )&& (p1!=null);i++){//p1先前移k-1 p1=p1.next; } if(p1==null){ System.out.println("k is illegal"); return null; } while(p1.next!=null){//p1,p2同前移 p1=p1.next; p2=p2.next; } return p2; } public static void main(String [] args){//简单测试,输出为1 int[] num={2,4,1,3,5,6}; Node head=new Node(); Node pre=head; for(int i=0;i<num.length;i++){ Node node=new Node(num[i]); pre.next =node; pre=node; } Node result=findElem(head,4); System.out.println(result.data); }}
eg4:从尾到头输出单链表
package linkedlist;/* * 方法一:链表中链接结点的指针反转改变链表方向,然后从尾到头输出 * 缺点:需要额外的操作 * 方法二:遍历链表,每经过一个结点,就把该结点放到一个栈中 * 遍历完后,从栈顶开始输出 * 缺点:需要维护一个额外的栈空间 * 方法三:递归,每访问一个结点,先递归输出它后面的结点,再输出该结点自身 */public class PrintListReversely { public static void printListReversely(Node pListHead){ if(pListHead!=null){ printListReversely(pListHead.next); System.out.println(pListHead.data); } } public static void main(String[] args) { // TODO Auto-generated method stub Node node1=new Node(2); Node node2=new Node(4); Node node3=new Node(1); node1.next=node2; node2.next=node3; printListReversely(node1); }}
阅读全文
0 0
- 链表(上)
- Anroid上的单元测试(上)
- 【数据结构】链表(上)
- 表达式求值(上)
- 打印位图(上)
- sfo聚会(上)
- log4j学习(上)
- Asp基础教程(上)
- 指针(上)
- socket_tutorial笔记(上)
- 人到中年(上)
- 打印位图(上)
- Asp基础教程(上)
- 编程修养(上)
- 戒痕(上)
- 租房记(上)
- iptables讲义(上)
- 深入浅出话回调(上)
- cassandra怎么获取所有表的字段名?
- Android Studio 3.0上分析内存泄漏的原因
- 4.故障恢复与备份
- 原生js伦比哦
- java动态绑定在属性和方法上的不同
- 链表(上)
- 对称加密和非对称加密
- static关键字
- 高并发下怎么做余额扣减?
- rabbitMQ结合spring框架使用
- IkAnalyzer分词后文章字符全角变半角,字母大写变小写问题
- 【LAMP环境搭建】MariaDB安装和Apache安装
- bracket 教程
- 状态栏沉浸式