数据结构-栈&队列&单向链表
来源:互联网 发布:ug五轴编程工资多少钱 编辑:程序博客网 时间:2024/05/22 08:22
栈
栈(Stack)是一种先进后出的数据结构。栈对于数据的操作只能从栈顶进行操作,新放入的数据都位于栈顶,也就是第一的位置,以前放入的就会被向下压,所以数据入栈也叫做压栈。
出栈的形式与入栈类似,每次都只能获取栈顶的元素。如我们要取得“200”就必须先取出“300”,然后再取一次才能成功取得“200”.
public class Test01_Stack { public static void main(String[] args) { String[] data = {"a","b","c","d","e"}; Stack<String> stack = new Stack<String>(); for(String s:data){ stack.push(s);// 入栈的方法 } for(int i=0;i<data.length;i++){ String s = stack.pop();// 出栈的方法 System.out.println(s);// e d c b a }// Stack类还有其他三个常用操作方法,可以通过查询API了解其使用方法 }}
- 使用栈的先进后出特性实现快速排序的非递归算法
public class Test03_quickSortNoRec { public static void main(String[] args) { int[] a = new int[20]; Random random = new Random(); for(int i=0;i<a.length;i++){ a[i] = random.nextInt(101); }// 产生随机数组 System.out.println(Arrays.toString(a)); quickSort(a);// 排序 System.out.println(Arrays.toString(a)); } private static void quickSort(int[] a) { Stack<Node> stack = new Stack<>();// 创建栈对象 stack.push(new Node(0,a.length-1));// 压栈,获得第一次排序的边界 while(!stack.empty()){// 当栈中空时,相当于所有的子递归全部实现 Node node = stack.pop();//出栈,取得当前排序的边界,相当于一次递归 int left = node.left; int right = node.right; boolean isRight = false;// 快速排序算法代码 // 降序排序 while(left < right){ if(a[left] < a[right]){ int t = a[left]; a[left] = a[right]; a[right] = t; isRight = !isRight; } if(isRight){ right--; }else{ left++; } } // 通过压栈,实现类似递归的功能 if(right+1 < node.right){ stack.push(new Node(right+1,node.right)); } if(left-1 > node.left){ stack.push(new Node(node.left,left-1)); } } }}class Node{// 封装类,存储一次排序的左右边界 public int left; public int right; public Node(int left, int right) { super(); this.left = left; this.right = right; }}
队列
队列是特殊的线性表,只允许在表的前端删除元素,在表的后端插入元素。所以队列是先进先出的数据结构。
- 为什么要使用队列:
- 计算机的任务调度系统
- 为了削减高峰时期订单请求,使用消息队列
- 其它数据结构比如树的广度优先遍历也需要借助队列来实现
- Android中用于实现线程间通信的消息队列是队列的典型应用之一
// 自定义类实现队列特性,在Java中,可以将LinkedList类用作队列public class MyQueue<E> { ArrayList<E> data = new ArrayList<E>(); public void push(E value){ data.add(value); } public E pop(){ E pop = data.remove(0); return pop; } public boolean isEmpty(){ return data.size()==0; } public E peek(){ E peek = data.get(0); return peek; } public int size(){ return data.size(); }}
链表(单向链表)
线性表是最基本、最简单、也最常用的一种数据结构。线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的。
一个链表是由节点组成的,类似于火车一样。每个链表(火车)有n个节点(车厢),一个节点内(车厢内)一部分内存(空间)用来存储数据值(乘客),还有一部分内存用来存储指向下一个节点的地址(通向下一节车厢的门的钥匙),我们通过访问这个地址(钥匙)就可以得到下一个节点(到达下一节车厢)。
// 自定义类实现链表的模拟public class Test06_LinkedList { public static void main(String[] args) { // 一个MyNode对象就是一个节点 MyNode<String> node = new MyNode<>("a");// 第一个节点 MyNode<String> head = node;// 头节点,火车头 // 第一个节点的next存放指向第二个节点的地址(钥匙) node.next = new MyNode<>("b"); // 通过钥匙进入下一车厢 node = node.next; // 第二个节点的next存放指向第三个节点的地址(钥匙) node.next = new MyNode<>("c"); node = node.next; // 回到头节点 node = head; // 遍历链表 while(node!=null){ String str = node.value;// 取得节点存储的数据值 System.out.println(str); node = node.next;// 跳向下一个节点 } }}
节点类
public class MyNode<T> { public T value;// 节点中存储的数据值 public MyNode<T> next;// 节点中存储的指向下一个节点的引用(钥匙) public MyNode(T value) { super(); this.value = value; } @Override public String toString() { return value.toString(); }}
- 链表中删除节点
public class Test07_LinkedList2 { public static void main(String[] args) { String[] data = {"a","b","c","d","e"}; MyNode<String> node = new MyNode<String>(data[0]); MyNode<String> head = node; for(int i=1;i<data.length;i++){ node.next = new MyNode<String>(data[i]); node = node.next; } Scanner scanner = new Scanner(System.in); int select; do{ System.out.println("1-删除首节点"); System.out.println("2-删除尾节点"); System.out.println("3-删除值为c的节点"); System.out.println("4-退出"); select = scanner.nextInt(); switch(select){ case 1: head = deleteFirstNode(head);// 删除首节点 myPrint(head); break; case 2: head = deleteLastNode(head);// 删除尾节点 myPrint(head); break; case 3: try { head = deleteKeyNode(head,"e");// 删除指定值的节点 myPrint(head); } catch (Exception e) { System.out.println(e.getMessage()); } break; } }while(select!=4);// 退出条件 scanner.close(); } /** * 删除指定值的节点 * @param head * @throws Exception */ private static MyNode<String> deleteKeyNode(MyNode<String> head, String key) throws Exception { if(head == null){ throw new Exception("链表不能为空"); } if(head.value.equals(key)){// 删除首节点的情况 head = deleteFirstNode(head); return head; } MyNode<String> node = head.next; MyNode<String> preNode = head; while(node.next!=null){ if(node.value.equals(key)){// 删除中间节点的情况 preNode.next = node.next; break; } preNode = node; node = node.next; } if(node.value.equals(key)){// 删除尾节点的情况 preNode.next = null; return head; } if(node.next==null){ throw new Exception("删除节点不存在"); } return head; } /** * 遍历链表,打印信息 * @param node */ private static void myPrint(MyNode<String> node) { while(node!=null){ System.out.println(node.value); node = node.next; } } /** * 删除尾节点 * @param head */ private static MyNode<String> deleteLastNode(MyNode<String> head) { if(head==null || head.next==null){ return null; } MyNode<String> result = head; while(head.next.next != null){ head = head.next; }// 找到倒数第二个节点 head.next = null;// 删除最后一个节点 return result; } /** * 删除首节点 * @param head * @return */ private static MyNode<String> deleteFirstNode(MyNode<String> head) { if(head==null){ return null; } head = head.next; return head; }}
练习
2.合并两个有序的链表,合并的链表仍然有序。
解题思路:
node1={1,3,5,7,9,12}
node2={2,4,6,8,10,11,13};
外循环遍历node2链表
内循环遍历node1链表,每次判断node2是否能插入到node1链表中,
不能则node1遍历至下一个节点。
能则退出内循环,将node2插入到node1链表中。
node2遍历至下一个节点。
public class HomeWork01 { public static void main(String[] args) { int[] arr1 = {1,3,5,7,9,12}; int[] arr2 = {2,4,6,8,10,11,13}; MyNode<Integer> head1 = createLinkedList(arr1);// 创建第一个链表 MyNode<Integer> head2 = createLinkedList(arr2);// 创建第二个链表 merge(head1, head2); myPrint(head1); } /** * 合并链表 * @param head1 被插入的目标链表 * @param head2 用来插入的数据链表 */ private static void merge(MyNode<Integer> head1, MyNode<Integer> head2) { while(head2!=null){ MyNode<Integer> node1=head1;// 获得被插入链表的首节点 int t = head2.value;// 获得要插入的链表的对应节点数据 MyNode<Integer> preNode=null; while(node1!=null){ if(t <= node1.value){// 升序排序 break; } preNode = node1; node1=node1.next; } MyNode<Integer> insert = new MyNode<>(t);// 通过要插入的数据创建新的节点 preNode.next = insert;// 将新的节点插入到目标链表中 insert.next = node1; head2 = head2.next;// 遍历数据链表,获得下一个需要插入的值 } } /** * 遍历链表,打印信息 * @param head1 */ private static void myPrint(MyNode<Integer> head1) { MyNode<Integer> node = head1; while(node!=null){ System.out.print(node.value + " "); node = node.next; } } /** * 创建链表 * @param arr1 * @return */ private static MyNode<Integer> createLinkedList(int[] arr1) { MyNode<Integer> node = new MyNode<Integer>(arr1[0]); MyNode<Integer> head = node; for(int i=1;i<arr1.length;i++){ node.next = new MyNode<Integer>(arr1[i]); node = node.next; } return head; }}
0 0
- 数据结构-栈&队列&单向链表
- 数据结构-单向链表
- 【数据结构】单向链表
- [数据结构] 单向链表
- 数据结构~~单向链表
- 数据结构单向链表
- 数据结构-单向链表
- 数据结构 单向链表
- 数据结构--单向链表
- 单向链表实现数据结构中的栈
- 数据结构之 (单向)队列
- 【数据结构】单向链表实例
- 数据结构之单向链表
- 数据结构之单向链表
- 数据结构之单向链表
- 数据结构之单向链表
- c++单向链表-数据结构
- 数据结构(单向链表)
- 送给所有还有梦想的人。
- static关键字2222222222222222222
- 【杭电oj5253】连接的管道
- CXF 发布WebService
- tarjan帮我来找桥
- 数据结构-栈&队列&单向链表
- 五个问题
- 奇怪的Dll中的stl内存泄露
- tjut 3746
- HDU 1509
- Appcompat导入后出错及Material Design 支持库导入出错的解决办法
- 设计模式之七大原则
- Apache Mina的IoService接口学习笔记
- 数据结构实验之排序七:选课名单