資料結構-棧&佇列&單向連結串列
棧
棧(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;
}
}
相關推薦
資料結構-棧&佇列&單向連結串列
棧 棧(Stack)是一種先進後出的資料結構。棧對於資料的操作只能從棧頂進行操作,新放入的資料都位於棧頂,也就是第一的位置,以前放入的就會被向下壓,所以資料入棧也叫做壓棧。 出棧的形式與入棧類似,每次都只能獲取棧頂的元素。如我們要取得“200”就必須先取
資料結構線性表—單向連結串列
單向連結串列 其實就是一種鏈式儲存的資料結構,它和陣列不同,陣列的儲存結構就是連續的,且長度是固定的。而連結串列不一樣,它可以是連續的,也可以是不連續的,而且是可以動態擴容的。 連結串列中的資料是以節點的形式表現出來的。結構為:資料+指標 ┌───┬───┐ │data│next│ └
Algorithm——簡單資料結構之佇列和連結串列(十三)
Algorithm——簡單資料結構之佇列和連結串列佇列是一種先進先出策略,而連結串列中的各元素按線性順序排列。陣列的線性順序是由陣列的下標決定的,但連結串列的順序是由各個物件裡的指標決定的。佇列有入隊和出隊操作,連結串列則有插入、刪除、查詢表中節點的操作。佇列和雙向連結串列的
資料結構---自定義單向連結串列(Java實現)
單向連結串列是指每一個節點記憶體在一個指向下一個節點的指標,java中就是節點存在指向下一個節點的物件引用 下面是Node節點類 public class Node { private Object object; private Node next;
15 API-集合(Collection(功能,迭代器),List(List特有迭代器,併發異常),常見資料結構圖示(棧,佇列,陣列,連結串列))&物件陣列
1:物件陣列(掌握) (1)陣列既可以儲存基本資料型別,也可以儲存引用型別。它儲存引用型別的時候的陣列就叫物件陣列。 (2)案例:用陣列儲存5個學生物件,並遍歷陣列。 學生的物件 public class Student { // 成員變數 private Stri
【資料結構】陣列、連結串列、棧、佇列、二叉樹
陣列 陣列儲存的資料在地址空間上是連續的。 方便資料的查詢,查詢資料的時間複雜度為O(1)。 連結串列 連結串列儲存的資料在地址空間上可連續,可不連續。 連結串列中的每一個節點都
重溫四大基礎資料結構:陣列、連結串列、佇列和棧
![file](https://img2020.cnblogs.com/other/1648938/202008/1648938-20200805081813714-1550683399.jpg) # 前言 > 本文收錄於專輯:[http://dwz.win/HjK](http://dwz.win/H
資料結構示例之用連結串列實現棧
以下是“使用連結串列實現棧”的簡單示例: 1. 用c語言實現的版本 #include<stdio.h> #include<stdlib.h> struct s_node { int data; struct s_node *next; };
【資料結構】【多項式連結串列實現相加】
#include<bits/stdc++.h> using namespace std; const int inf = 0x3f3f3f3f; const int maxn = 1006; struct node { double coef; int exp; struct n
資料結構 筆記:迴圈連結串列的實現
什麼事迴圈連結串列? -概念上 ·任意資料元素都有一個前驅和一個後繼 ·所有的資料元素的關係構成一個邏輯上的環 -實現上 ·迴圈連結串列是一種特殊的單鏈表 ·尾結點的指標域儲存了首結點的地址 迴圈連結串列的實現思路 -通過模板定義CircleList類,繼承自L
資料結構之——陣列和連結串列
1. 陣列 1.1 陣列為什麼從零編號? 陣列名代表陣列的首地址,陣列的下標其實代表陣列中某個元素相對首地址的偏移量,陣列的第一個元素是零偏移,因此從 0 開始。 上面其實也只是一個解釋, C 語言設計者用零開始編號,後來的各種語言也便紛紛效仿,因此就形成了這個習慣。 1
《java常用演算法手冊》 第二章 資料結構 棧 佇列
順序棧的實現: package LineStructure; //參考 https://blog.csdn.net/icarus_wang/article/details/79561863 public cla
資料結構實驗三靜態連結串列學生資訊
#include<iostream> #include<string> using namespace std; //靜態連結串列的儲存結構 c
資料結構:陣列和連結串列的區別以及各自的優缺點
原文地址 http://blog.csdn.net/qq_25806863/article/details/70607204 陣列和連結串列是兩種基本的資料結構,他們在記憶體儲存上的表現不一樣,所以也有各自的特點。 大致總結一下特點和區別,拿幾個人一起去看電影時坐座位為例。 陣列的特點
資料結構與演算法之連結串列篇(上)
連結串列作為一種基礎的資料結構之一,我們會常常使用到它,接下來就讓我們一起學習吧。 1、連結串列的經典應用場景: LRU快取淘汰演算法。 2、快取是一種提高資料讀取效能的技術,在硬體設計、軟體開發中都有著非常廣泛的應用,比如常見的CPU快取、資料庫快取、瀏覽器快取等等。
資料結構與演算法之連結串列篇(下)
Q:如何輕鬆寫出正確的連結串列程式碼? 總結起來,就是投入時間+技巧; 一、投入時間: 只要願意投入時間,大多數人都是可以學會的,比如說,如果你真能花上一個週末或者一整天時間,就去寫連結
Java資料結構(一)——連結串列
Java中的資料結構又很多種,如棧,佇列,樹等,但是他們的形式歸根到底就是兩種:一個是陣列,一個是連結串列,所有的結構都是對這兩個的變形。 什麼是線性表? 陣列和連結串列都屬於是線性表,那什麼是線性表:一個線性表是n個相同特性的資料元素的有序序列。各元素之間是一對一的關係。但這並不是
java版資料結構與演算法—有序連結串列
package com.zoujc.sortLink; /** * 有序連結串列 */ class Link { public int dData; public Link next; public Link(int dd){ dData = d
【資料結構與演算法】連結串列——遞增排序
今天看書時偶然想到的問題,書上是要求將一個數據插入一個有序連結的線性連結串列中, 所以我想先進行連結串列內的資料排序在進行插入資料。 在這裡我只寫了排序的函式。 函式實現: void Sort(LinkList&list, int &n) { f
自己動手實現java資料結構(二) 連結串列
1.連結串列介紹 前面我們已經介紹了向量,向量是基於陣列進行資料儲存的線性表。今天,要介紹的是線性表的另一種實現方式---連結串列。 連結串列和向量都是線性表,從使用者的角度上依然被視為一個線性的列表結構。但是,連結串列內部儲存資料的方式卻和向量大不相同:連結串列的核心是節點。節點儲存"資料"的同