数据结构
Posted sakura1027
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构相关的知识,希望对你有一定的参考价值。
栈和队列
1. 栈的实现
1 //基于数组实现的栈 2 public class ArrayStack { 3 private int[] arr; 4 private int top; 5 6 ArrayStack(int initialSize){ 7 if(initialSize<=0) 8 throw new RuntimeException("栈初始化容量参数错误:"+initialSize); 9 top=-1; 10 arr=new int[initialSize]; 11 } 12 13 public int push(int x){ 14 if(top==arr.length-1) 15 throw new RuntimeException("栈已满,无法入栈!"); 16 arr[++top]=x; 17 return x; 18 } 19 20 public int pop(){ 21 if(top<0) 22 throw new RuntimeException("栈为空!"); 23 return arr[top--]; 24 } 25 26 public int peek(){ 27 if(top<0) 28 throw new RuntimeException("栈为空!"); 29 return arr[top]; 30 } 31 32 public boolean isEmpty(){ 33 return top==-1; 34 } 35 36 public static void main(String[] args) { 37 ArrayStack ms=new ArrayStack(10); 38 for(int i=0;i<5;i++) 39 System.out.println("添加了"+ms.push(i)); 40 System.out.println("栈是否为空:"+ms.isEmpty()); 41 System.out.println(ms.peek()); 42 for(int i=0;i<5;i++) 43 System.out.println("删除了"+ms.pop()); 44 System.out.println(ms.isEmpty()); 45 ms.peek(); 46 } 47 } 48 /* 49 Exception in thread "main" java.lang.RuntimeException: 栈为空! 50 添加了0 51 添加了1 52 at com.sakura.alg.ArrayStack.peek(ArrayStack.java:31) 53 添加了2 54 at com.sakura.alg.ArrayStack.main(ArrayStack.java:48) 55 添加了3 56 添加了4 57 栈是否为空:false 58 4 59 删除了4 60 删除了3 61 删除了2 62 删除了1 63 删除了0 64 true 65 */
1 import java.util.EmptyStackException; 2 import java.util.LinkedList; 3 4 //基于链表实现的栈 5 public class ListStack { 6 private LinkedList<Integer> l=new LinkedList<>(); 7 8 public int push(int x){ 9 l.addLast(x); 10 return x; 11 } 12 13 public int pop(){ 14 if(l.size()<=0) 15 throw new EmptyStackException(); 16 return l.removeLast(); 17 } 18 19 public int peek(){ 20 if(l.size()<=0) 21 throw new EmptyStackException(); 22 return l.getLast(); 23 } 24 25 public boolean isEmpty(){ 26 return l.size()==0; 27 } 28 29 public static void main(String[] args) { 30 ListStack ms=new ListStack(); 31 for(int i=0;i<5;i++) 32 System.out.println("添加了"+ms.push(i)); 33 System.out.println("栈是否为空:"+ms.isEmpty()); 34 System.out.println(ms.peek()); 35 for(int i=0;i<5;i++) 36 System.out.println("删除了"+ms.pop()); 37 System.out.println(ms.isEmpty()); 38 ms.peek(); 39 } 40 } 41 /* 42 Exception in thread "main" java.util.EmptyStackException 43 添加了0 44 at com.sakura.alg.ListStack.peek(ListStack.java:23) 45 添加了1 46 at com.sakura.alg.ListStack.main(ListStack.java:40) 47 添加了2 48 添加了3 49 添加了4 50 栈是否为空:false 51 4 52 删除了4 53 删除了3 54 删除了2 55 删除了1 56 删除了0 57 true 58 */
2. 队列实现
1 public class ArrayQueue { 2 private int[] arr; 3 private int head; 4 private int tail; 5 6 ArrayQueue(int initialSize){ 7 if(initialSize<=0) 8 throw new RuntimeException("队列初始化容量参数错误:"+initialSize); 9 arr=new int[initialSize]; 10 head=tail=0; 11 } 12 13 public boolean isEmpty(){ 14 return tail<=0||head>=tail; 15 } 16 17 public int add(int x){ 18 if(tail==arr.length) 19 throw new RuntimeException("队列已满,无法入队!"); 20 arr[tail++]=x; 21 return x; 22 } 23 24 public int peek(){ 25 if(tail<=0||head>=tail) 26 throw new RuntimeException("队列为空!"); 27 return arr[head]; 28 } 29 30 public int poll(){ 31 if(tail<=0||head>=tail) 32 throw new RuntimeException("队列为空!"); 33 return arr[head++]; 34 } 35 36 public static void main(String[] args) { 37 ArrayQueue mq=new ArrayQueue(10); 38 for(int i=0;i<5;i++) 39 System.out.println("添加了"+mq.add(i)); 40 System.out.println("队列是否为空:"+mq.isEmpty()); 41 System.out.println(mq.peek()); 42 for(int i=0;i<5;i++) 43 System.out.println("删除了"+mq.poll()); 44 System.out.println(mq.isEmpty()); 45 mq.peek(); 46 } 47 48 } 49 /* 50 Exception in thread "main" java.lang.RuntimeException: 队列为空! 51 添加了0 52 添加了1 53 添加了2 54 添加了3 55 添加了4 56 队列是否为空:false 57 0 58 at com.sakura.alg.ArrayQueue.peek(ArrayQueue.java:28) 59 删除了0 60 at com.sakura.alg.ArrayQueue.main(ArrayQueue.java:47) 61 删除了1 62 删除了2 63 删除了3 64 删除了4 65 true 66 */
1 import java.util.LinkedList; 2 import java.util.Queue; 3 4 public class ListQueue { 5 private Queue<Integer> queue=new LinkedList<>(); 6 7 public int peek(){ 8 return queue.peek(); 9 } 10 11 public boolean offer(int x){ 12 return queue.offer(x); 13 } 14 15 public int poll(){ 16 return queue.poll(); 17 } 18 19 public boolean isEmpty() { 20 return queue.isEmpty(); 21 } 22 23 public static void main(String[] args) { 24 ListQueue mq=new ListQueue(); 25 for(int i=0;i<5;i++) 26 mq.offer(i); 27 System.out.println("队列是否为空:"+mq.isEmpty()); 28 System.out.println(mq.peek()); 29 for(int i=0;i<5;i++) 30 System.out.println("删除了"+mq.poll()); 31 System.out.println(mq.isEmpty()); 32 mq.peek(); 33 } 34 35 } 36 /* 37 队列是否为空:false 38 Exception in thread "main" java.lang.NullPointerException 39 at com.sakura.alg.ListQueue.peek(ListQueue.java:10) 40 0 41 at com.sakura.alg.ListQueue.main(ListQueue.java:34) 42 删除了0 43 删除了1 44 删除了2 45 删除了3 46 删除了4 47 true 48 */
3. 两个栈实现一个队列
1 import java.util.Stack; 2 3 public class MyQueue { 4 private Stack<Integer> stack=new Stack<>(); 5 private Stack<Integer> stack2=new Stack<>(); 6 7 public int offer(int x){ 8 stack.push(x); 9 return x; 10 } 11 12 public int poll(){ 13 if(stack2.isEmpty()) 14 while(!stack.isEmpty()) 15 stack2.push(stack.pop()); 16 17 if(stack2.isEmpty()) 18 throw new RuntimeException("队列为空!"); 19 return stack2.pop(); 20 } 21 22 public static void main(String[] args) { 23 MyQueue mq=new MyQueue(); 24 for(int i=0;i<5;i++) 25 mq.offer(i); 26 mq.poll(); 27 System.out.println(mq.poll());//1 28 } 29 30 }
4. 两个队列实现一个栈
1 import java.util.LinkedList; 2 import java.util.Queue; 3 4 public class MyStack { 5 private Queue<Integer> queue1=new LinkedList<>(); 6 private Queue<Integer> queue2=new LinkedList<>(); 7 8 public int push(int x){ 9 if(!queue1.isEmpty()) 10 queue1.offer(x); 11 else 12 queue2.offer(x); 13 return x; 14 } 15 16 public int pop(){ 17 if(queue1.isEmpty()&&queue2.isEmpty()) 18 throw new RuntimeException("栈为空!"); 19 if(queue1.isEmpty()){ 20 while(queue2.size()>1) 21 queue1.offer(queue2.poll()); 22 return queue2.poll(); 23 }else{ 24 while(queue1.size()>1) 25 queue2.offer(queue1.poll()); 26 return queue1.poll(); 27 } 28 } 29 30 public static void main(String[] args) { 31 MyStack ms=new MyStack(); 32 for(int i=0;i<5;i++) 33 System.out.println("添加了"+ms.push(i)); 34 System.out.println(ms.pop()); 35 36 System.out.println("添加了"+ms.push(5)); 37 for(int i=0;i<5;i++) 38 System.out.println(ms.pop()); 39 } 40 41 } 42 /* 43 添加了0 44 添加了1 45 添加了2 46 添加了3 47 添加了4 48 4 49 添加了5 50 5 51 3 52 2 53 1 54 0 55 */
5. 设计含最小函数min的栈
1 import java.util.Stack; 2 3 public class MinStack { 4 Stack<Integer> stack; 5 Stack<Integer> stackMin; 6 7 public MinStack() { 8 this.stack=new Stack<>(); 9 this.stackMin=new Stack<>(); 10 } 11 12 public void push(int x) { 13 stack.push(x); 14 if(stackMin.isEmpty()) 15 stackMin.push(x); 16 else if(stackMin.peek()<x) 17 stackMin.push(stackMin.peek()); 18 else 19 stackMin.push(x); 20 } 21 22 public void pop() { 23 if(!stack.isEmpty()&&!stackMin.isEmpty()){ 24 stack.pop(); 25 stackMin.pop(); 26 }else{ 27 System.out.println("栈已经没有元素了..."); 28 } 29 } 30 31 public int top() { 32 return stack.peek(); 33 } 34 35 public int getMin() { 36 return stackMin.peek(); 37 } 38 }
6. 判断出栈序列是否合法
1 import java.util.Stack; 2 3 public class SeqStack { 4 public static boolean IsPopOrder(int [] pushA,int [] popA) { 5 Stack<Integer> s = new Stack<>(); 6 int popIndex = 0; 7 for(int i = 0; i< pushA.length;i++){ 8 s.push(pushA[i]); 9 while(!s.empty() &&s.peek() == popA[popIndex]){ 10 s.pop(); 11 popIndex++; 12 } 13 } 14 return s.empty(); 15 } 16 17 public static void main(String[] args) { 18 int[] arr={1,2,3,4,5}; 19 int[] brr={5,4,3,2,1}; 20 System.out.println(IsPopOrder(arr,brr)); 21 } 22 }
链表
1 import java.util.Stack; 2 3 public class LinkList { 4 static class Node { 5 int data; 6 Node next; 7 8 public Node(int data) { 9 this.data = data; 10 } 11 } 12 13 public Node head; 14 public Node current; 15 16 //创建链表 17 public void add(int data) { 18 if (head == null) { 19 head = new Node(data); 20 current = head; 21 } else { 22 current.next = new Node(data); 23 current = current.next; 24 } 25 } 26 27 public void add(Node node) { 28 if (node == null) 29 return; 30 if (head == null) { 31 head = node; 32 current = head; 33 } else { 34 current.next = node; 35 current = current.next; 36 } 37 } 38 39 //遍历输出链表 40 public static void print(Node node) { 41 if (node == null) 42 return; 43 Node current = node; 44 while (current.next != null) { 45 System.out.print(current.data+"->"); 46 current = current.next; 47 } 48 System.out.println(current.data); 49 } 50 51 //获得链表节点个数 52 public static int getLength(Node head){ 53 if(head==null) 54 return 0; 55 int count=0; 56 Node current=head; 57 while(current!=null){ 58 count++; 59 current=current.next; 60 } 61 return count; 62 } 63 64 //查找倒数第k个节点 65 public static int findLastNode(Node head,int k){ 66 if(k==0||head==null) 67 return -1; 68 int size=getLength(head); 69 if(k>size) 70 return -1; 71 Node cur=head; 72 for(int i=0;i<size-k;i++){ 73 cur=cur.next; 74 } 75 return cur.data; 76 } 77 78 //在不允许遍历链表长度的情况下查找倒数第k个节点 79 public static int findLastNode2(Node head,int k){ 80 if(k==0||head==null) 81 return -1; 82 Node first=head,second=head; 83 for(int i=0;i<k-1;i++){ 84 second=second.next; 85 if(second==null) 86 return -1; 87 } 88 89 while(second.next!=null){ 90 first=first.next; 91 second=second.next; 92 } 93 return first.data; 94 } 95 96 //查找中间节点 97 public static int findMidNode(Node head){ 98 if(head==null) 99 return -1; 100 Node first=head,second=head; 101 while(second!=null&&second.next!=null){ 102 first=first.next; 103 second=second.next.next; 104 } 105 return first.data; 106 } 107 108 //合并两个有序链表 109 public static Node mergeTwoLists(Node l1, Node l2) { 110 if(l1==null) 111 return l2; 112 if(l2==null) 113 return l1; 114 if(l1.data < l2.data){ 115 l1.next = mergeTwoLists(l1.next, l2); 116 return l1; 117 } else{ 118 l2.next = mergeTwoLists(l1, l2.next); 119 return l2; 120 } 121 } 122 123 //循环翻转 124 public static Node ReverseListByLoop(Node head) { 125 Node pre = null; 126 Node next = null; 127 while(head!=null){ 128 next = head.next; 129 head.next = pre; 130 pre = head; 131 head = next; 132 } 133 return pre; 134 } 135 136 //递归翻转 137 public static Node ReverseListByRecursion(Node head){ 138 if(head==null||head.next ==null) 139 return head; 140 Node prev = ReverseListByRecursion(head.next); 141 head.next.next = head; 142 head.next = null; 143 return prev; 144 } 145 146 //从尾到头打印链表 147 public static void reversePrint(Node head){ 148 if(head==null) 149 return; 150 Stack<Node> stack=new Stack<>(); 151 Node current=head; 152 while(current!=null){ 153 stack.push(current); 154 current=current.next; 155 } 156 while(!stack.isEmpty()){ 157 System.out.print(stack.pop().data+" "); 158 } 159 System.out.println(); 160 } 161 162 //判断单链表是否有环 163 public static Node hasCycle(Node head) { 164 if(head==null) 165 return null; 166 Node first = head,second=head; 167 168 while (second != null&&second.next!=null) { 169 first = first.next; 170 second = second.next.next; 171 if (first == second) 172 return first; 173 } 174 return null; 175 } 176 177 //获取有环链表的环的长度 178 public static int getCycleLength(Node node) { 179 Node current = node; 180 int length = 0; 181 while (current != null) { 182 current = current.next; 183 length++; 184 if (current == node) 185 return length; 186 } 187 return length; 188 } 189 190 //取出环的起点 191 public static Node getCycleStart(Node head) { 192 if(head==null) 193 return null; 194 Node first = head,second=head; 195 196 while (second != null&&second.next!=null) { 197 first = first.next; 198 second = second.next.next; 199 if (first == second){ 200 second=head; 201 /* 202 假设链表起点到环的起点为x 203 链表起点到快慢指针相遇节点为x+z 204 环的长度为y 205 那么有2(x+z)-(x+z)=k*y 206 即x=k*y-z=y-z+(k-1)*y 207 */ 208 while(first!=second){ 209 first=first.next; 210 second=second.next; 211 } 212 return first; 213 } 214 215 } 216 return null; 217 } 218 219 /* 220 判断两个单链表相交的第一个节点 221 1.压入栈中,依次比较找出最后一个相同的节点,时间空间复杂度均为O(len1+len2) 222 2.快慢指针 223 */ 224 public static Node getFirstCommonNode(Node head1, Node head2) { 225 if (head1 == null || head2 == null) 226 return null; 227 int length1 = getLength(head1); 228 int length2 = getLength(head2); 229 int lengthDif=Math.abs(length1-length2); 230 Node longHead=length1>length2?head1:head2, 231 shortHead=length1>length2?head2:head1; 232 233 for (int i = 0; i < lengthDif; i++) 234 longHead = longHead.next; 235 236 while (longHead != null && shortHead != null) { 237 if (longHead == shortHead) 238 return longHead; 239 longHead = longHead.next; 240 shortHead = shortHead.next; 241 } 242 return null; 243 } 244 245 public static void main(String[] args) { 246 LinkList list = new LinkList(); 247 for (int i = 0; i < 10; i++) { 248 list.add(i); 249 } 250 print(list.head); 251 System.out.println(getLength(list.head)); 252 System.out.println(findLastNode(list.head,4)); 253 System.out.println(findLastNode2(list.head,10)); 254 System.out.println(findMidNode(list.head)); 255 256 LinkList list2=new LinkList(); 257 for(int i=0;i<10;i+=2){ 258 list2.add(i); 259 } 260 print(list2.head); 261 LinkList list3=new LinkList(); 262 for(int i=1;i<10;i+=2){ 263 list3.add(i); 264 } 265 print(list3.head); 266 print(mergeTwoLists(list2.head,list3.head)); 267 268 Node head=ReverseListByLoop(list.head); 269 print(head); 270 print(ReverseListByRecursion(head)); 271 272 reversePrint(list.head); 273 274 System.out.println(hasCycle(list.head)); 275 276 LinkList list4=new LinkList(); 277 for(int i=0;i<10;i++){ 278 list4.add(i); 279 } 280 list4.add(list4.head.next); 281 282 System.out.println(getCycleLength(hasCycle(list4.head))); 283 System.out.println(getCycleStart(list4.head).data); 284 285 Node n1=new Node(1); 286 Node n2=new Node(2); 287 Node n3=new Node(3); 288 Node n4=new Node(4); 289 Node n5=new Node(5); 290 291 LinkList list5=new LinkList(); 292 list5.add(n1); 293 list5.add(n2); 294 list5.add(n3); 295 list5.add(n4); 296 list5.add(n5); 297 LinkList list6=new LinkList(); 298 list6.add(n2); 299 list6.add(n3); 300 list6.add(n4); 301 list6.add(n5); 302 System.out.println(getFirstCommonNode(list5.head,list6.head).data); 303 } 304 305 }
以上是关于数据结构的主要内容,如果未能解决你的问题,请参考以下文章
python 用于数据探索的Python代码片段(例如,在数据科学项目中)