數據結構與算法-Rust 版讀書筆記-2線性數據結構-棧

數據結構與算法-Rust 版讀書筆記-2線性數據結構-棧

一、線性數據結構概念

數組、棧、隊列、雙端隊列、鏈表這類數據結構都是保存數據的容器,數據項之間的順序由添加或刪除時的順序決定,數據項一旦被添加,其相對于前后元素就會一直保持位置不變,諸如此類的數據結構被稱為線性數據結構。

線性數據結構有兩端,稱為“左”和“右”,在某些情況下也稱為“前”和“后”,當然也可以稱為頂部和底部,名稱不重要,重要的是這種命名展現出的位置關系表明了數據的組織方式是線性的。這種線性特性和內存緊密相關,因為內存就是一種線性硬件,由此也可以看出軟件和硬件是如何關聯在一起的。

線性數據結構說的并非數據的保存方式,而是數據的訪問方式。

線性數據結構不一定代表數據項在內存中相鄰。以鏈表為例,雖然其中的數據項可能在內存的各個位置,但訪問是線性的。

區分不同線性數據結構的方法是查看它們添加和移除數據項的方式,特別是添加和移除數據項的位置。例如,一些數據結構只允許從一端添加數據項,另一些則允許從另一端移除數據項,還有的允許從兩端操作數據項。這些變種及其組合形式產生了許多在計算機科學領域非常有用的數據結構,它們出現在各種算法中,用于執行各種實際且重要的任務。

1、棧:后進先出

棧是數據項的有序集合,其中,新項的添加和移除總發生在同一端,這一端稱為頂部,與之相對的另一端稱為底部。棧的底部很重要,因為棧中靠近底部的項是存儲時間最長的,最近添加的項最先被移除。這種排序原則有時被稱為后進先出(Last In First Out,LIFO)或先進后出(First In Last Out,FILO),所以較新的項靠近頂部,較舊的項靠近底部。

2、Rust 預備知識

1、trait

trait類似于Java中的接口,TS 的 interface,C++中的純虛類,但卻又不完全相同。

trait這個單詞,本意為特征,在代碼中的含義就是,讓某個結構體擁有某個特征。

trait Shape {fn area(&self) -> f32{return 0.0; } //該函數是實現可寫可不寫,如果不寫,那么實現該Trait的結構就必須寫,如果這里寫了,那么后面實現該trait的結構就可以不寫fn test(){println!("不寫self參數,則只能通過 :: 的方式進行調用");}
}struct triangle{ //為了簡單,假設其是直角三角形,存放兩個直角邊a: f32,b: f32,
}impl Shape for triangle {fn area(&self) -> f32 {return (self.a*self.b)/2.0;}
}struct square{a: f32
}impl Shape for square {fn area(&self) -> f32 {return self.a*self.a;}
}

通過 trait Shape,使得 triangle、square 都具有了 area 方法。

調用方式:

fn main() {let t=triangle{a: 1.0, b: 2.0};let s=square{a:4.0};//調用帶有self參數的函數t.area();s.area();//調用沒有self參數的函數triangle::test();square::test();
}

其中area函數的參數帶有self,也就是要與具體的結構體對應,調用的時候要用.的方式。

另一種調用方式:

fn main() {let t=triangle{a: 1.0, b: 2.0};let s=square{a:4.0};//調用帶有self參數的函數test_area(&t);test_area(&s);
}fn test_area(shape: &impl Shape){shape.area();
}

用 test_area 函數倆輸出,這個函數的參數為 &impl Shape,意思是:接受實現了這個 Shape trait 的結構體的引用。

這是不是就和println!宏非常像了!現在只要你的任意形狀結構體實現了這個Shape的trait,那么我就能用一個統一的方法(test_area)來輸出你的內容!

所以:

只要你自定義了一個結構體,你想要讓他可以被println!打印出來,你就得為其實現這個trait

如果要拷貝,那就請你實現Clone這個trait,并且顯式的調用clone這個函數,讓你自己清楚的認識到此刻你是在完成一個拷貝數據的工作

#[derive(Clone)]
struct Stu{name: String,age:u32
}fn main() {let s1=Stu{name:String::from("yushi-"),age:100};let s2=s1.clone(); //讓你能清醒的認識到自己在完成一個拷貝的工作println!("{}:{}", s1.name,s1.age); //可用,因為是將內容拷貝給了s2一份println!("{}:{}", s2.name,s2.age);
}

最常用的trait,除了CopyClone,還有三個:DebugDefaultPartialEq

其中,Debug是方便我們調試用的:

#[derive(Debug)]
struct Stu{name: String,age:u32
}
fn main() {let s1=Stu{/*省略代碼*/};println!("{:?}", s1);
}

只要你用了Debug這個trait,那么你就無需實現Display這個trait,也可以方便的打印出相關信息

唯一需要注意的點就是,打印Debug信息,你需要在{}中添加:?

如果你還想要打印格式化后的格式信息,讓結構更好看,還可以這樣寫:

println!("{:#?}", s1);
2、Vec

Vec 是一種動態數組,它可以在運行時自動調整大小。

Vec是Rust標準庫的一部分,提供了一種高效、安全的方式來處理大量數據。

基于堆內存申請的連續動態數據類型,其索引、壓入(push)、彈出(pop) 操作的時間復雜度為 O(1) 。

Vec 是 vector 的縮寫。

Vec的底層實現是基于數組的,因此它的性能非常高。Vec可以存儲任何類型的數據,包括整數、浮點數、字符串等。

Vec其實是一個智能指針,用于在堆上分配內存的動態數組。它提供了一些方法來操作數組,如添加、刪除和訪問元素。與C或Python中的數組不同,Vec會自動處理內存分配和釋放,從而避免了常見的內存泄漏和懸掛指針錯誤。

Vec的本質就是一個三元組,指針、長度、容量,在rust標準庫中的定義如下:

pub struct Vec<T, A: Allocator = Global> {buf: RawVec<T, A>,len: usize,
}
impl<T> Vec<T> {#[inline]pub const fn new() -> Self {Vec { buf: RawVec::NEW, len: 0 }}
//...略...
}

Vec的核心功能之一是動態增長和收縮。當向Vec中添加元素時,如果堆上的內存不足,Vec會自動分配更多的內存來容納元素。這個過程稱為“擴容”。同樣,當從Vec中刪除元素時,如果堆上的內存過多,Vec會自動收縮以釋放內存。這個過程稱為“縮容”。這種自動內存管理機制使得使用Vec變得非常方便,同時也避免了手動管理內存的錯誤。

除了基本的添加、刪除和訪問元素操作之外,Vec還提供了許多其他功能。例如,它們可以按索引訪問元素,可以使用迭代器遍歷元素,并且支持多種方法(如push()、pop()、insert()和remove())來修改Vec的內容。Vec還提供了一些有用的靜態方法(如capacity()、len()和is_empty()),可以用來獲取Vec的屬性。

雖然Vec是一個非常強大的數據結構,但它們也有一些限制。例如,Vec在堆上分配內存,這意味著訪問元素的速度可能會比在棧上分配內存的數組慢。此外,由于Vec是智能指針,因此它們的大小不是固定的,這可能會導致一些編程錯誤。例如,如果嘗試將Vec賦值給一個固定大小的數組或另一個Vec,則會發生編譯時錯誤。

在這里插入圖片描述

Vec::new()方法

只創建一個空列表時,必須注明類型(否則通不過編譯)。

fn main() {let vec: Vec<i32> = Vec::new();println!("{:?}", vec);
}
Vec::from()方法
 let vec = Vec::from([1,2,3]);
vec! 宏

用于判斷是否相等

fn main() {let vec1 = Vec::from([1,2,3]);println!("{:?}", vec1);let vec2 = vec![1,2,3];println!("{:?}", vec2);assert_eq!(vec1, vec2);assert_eq!(vec1, [1,2,3]);assert_eq!(vec2, [1,2,3]);println!("{}", vec1 == vec2); // 輸出 true
}

創建相同元素 n 的 vec

fn main() {let vec = vec![0; 5];assert_eq!(vec, [0, 0, 0, 0, 0]);println!("{:?}", vec);let vec = vec![1; 3];assert_eq!(vec, [1, 1, 1]);println!("{:?}", vec);let vec = vec![1; 0];
}

因為是數組,所以還有 pop、splice、sort 等等數組具有的方法。

3、impl

**impl是一個關鍵字,用于在類型上實現方法。它是將函數與特定類型(結構體或枚舉)關聯起來的一種方式。impl**主要有兩種用途:

1、實現方法:你可以為特定類型定義方法。然后可以在該類型的實例上調用這些方法。

struct Rectangle {width: u32,height: u32,
}impl Rectangle {fn area(&self) -> u32 {self.width * self.height}
}

在這個示例中,為**Rectangle結構體實現了一個名為area**的方法,用于計算矩形的面積。

2、實現特質(Traits):Rust中的特質(Trait)類似于其他語言中的接口。它們定義了類型必須提供的功能。使用**impl**,你可以為特定類型實現一個特質,提供特質中定義的必要方法。

trait Describable {fn describe(&self) -> String;
}impl Describable for Rectangle {fn describe(&self) -> String {format!("Rectangle of width {} and height {}", self.width, self.height)}
}

在這里,為**Rectangle實現了Describable**特質,提供了描述矩形的具體方式。

impl 塊中定義的函數可以是獨立的,這意味著將其稱為 Foo::bar()。 如果函數以 self&self&mut self 作為它的第一個參數,那么也可以使用方法調用語法調用它,這是任何面向對象的程序員都熟悉的特性,比如 foo.bar ()

4、Self

通常在 Rust 的 trait 和 associated function 中使用 Self 來指代實現該 trait 或調用該 associated function 的類型。

struct Point {x: f32,y: f32,
}impl Point {//關聯函數fn origin() -> Self {Point { x: 0.0, y: 0.0 }}
}fn main() {let p = Point::origin();
}
5、self

self 是一個代表**類型實例(或者是類型的引用或者是值)**的關鍵字,在 Rust 的方法中使用 self 可以引用當前類型的實例或者類型本身。

具體來說,當我們定義一個方法時,使用 self 關鍵字作為方法的第一個參數可以讓我們在調用該方法時直接訪問類型實例本身

struct Point {x: f32,y: f32,
}impl Point {fn distance(&self, other: &Point) -> f32 {let dx = self.x - other.x;let dy = self.y - other.y;(dx * dx + dy * dy).sqrt()}
}
6、 . 和 ::

在Rust中,.::操作符都可以用來調用方法,但它們的用法有所不同。

.操作符用于調用實例方法。實例方法是定義在類型上的方法,它需要一個類型的實例作為第一個參數(通常稱為self)。**而實例方法(instance methods)與其他語言中的動態方法(dynamic methods)類似。都需要先聲明一個實例后,才可以用的方法。**例如,下面是一個簡單的結構體和一個實例方法的示例:

在這里插入圖片描述

上面的代碼定義了一個名為Point的結構體,它有兩個字段xy。然后,我們在impl Point塊中定義了一個名為distance_from_origin的實例方法。這個方法接受一個名為self的參數,它表示調用該方法的實例。在這個方法中,我們使用了self.xself.y來訪問實例的字段。

main函數中,我們創建了一個名為pPoint實例,并使用.操作符來調用它的實例方法。也就是說,我們使用了語句p.distance_from_origin()來調用該方法。

::操作符則用于調用關聯函數。**關聯函數也是定義在類型上的函數,但它不需要一個類型的實例作為第一個參數。Rust中的關聯函數(associated functions)與其他語言中的靜態方法(static methods)類似。**例如,下面是一個簡單的結構體和一個關聯函數的示例:

在這里插入圖片描述

上面的代碼定義了一個名為Point的結構體,它有兩個字段xy。然后,我們在impl Point塊中定義了一個名為new的關聯函數。這個函數接受兩個參數:x和y,并返回一個新創建的Point實例。

在main函數中,我們使用::操作符來調用Point類型上的關聯函數。也就是說,我們使用了語句Point::new(3, 4)來調用該函數。

實例方法通常用于操作類型的實例。例如,您可以定義一個Point結構體,它有兩個字段xy,然后定義一個實例方法來計算點到原點的距離。這個方法需要一個Point類型的實例作為第一個參數,然后使用這個實例的字段來進行計算。

關聯函數通常用于執行與類型相關但不依賴于類型實例的操作。例如,您可以定義一個關聯函數來創建一個新的Point實例。這個函數不需要一個Point類型的實例作為第一個參數,而是接受一些參數來初始化新創建的實例。

在選擇使用實例方法還是關聯函數時,您應該考慮您要執行的操作是否依賴于類型的實例。如果是,則應該使用實例方法;否則,應該使用關聯函數。

7、self 和 &self、mut 和 &mut

&self,表示向函數傳遞的是一個引用,不會發生對象所有權的轉移;

self,表示向函數傳遞的是一個對象,會發生所有權的轉移,對象的所有權會傳遞到函數中。

let b = a;
含義:a綁定的資源A轉移給b,b擁有這個資源A

let b = &a;  
含義:a綁定的資源A借給b使用,b只有資源A的讀權限

let b = &mut a;  
含義:a綁定的資源A借給b使用,b有資源A的讀寫權限

let mut b = &mut a;  
含義:a綁定的資源A借給b使用,b有資源A的讀寫權限。同時,b可綁定到新的資源上面去(更新綁定的能力)

fn do(c: String) {}  
含義:傳參的時候,實參d綁定的資源D的所有權轉移給c

fn do(c: &String) {}  
含義:傳參的時候,實參d將綁定的資源D借給c使用,c對資源D只讀

fn do(c: &mut String) {}  
含義:傳參的時候,實參d將綁定的資源D借給c使用,c對資源D可讀寫

fn do(mut c: &mut String) {}  
含義:傳參的時候,實參d將綁定的資源D借給c使用,c對資源D可讀寫。同時,c可綁定到新的資源上面去(更新綁定的能力)

8、Option<T>

Option<T> 是 Rust 中的類型系統,來傳播和處理錯誤的類型。

pub enum Option<T> {None,Some(T),
}

Option<T>是一個枚舉類型,要么是Some<T>,要么是None。這能很好地表達有值和無值兩種情況,避免出現Java中的NullPointerException

9、’ 生命周期標記

生命周期用單引號’加字母表示,置于&后,如&'a、&mut 't

10、unwrap

有的時候我們不想處理或者讓程序自己處理 Err, 有時候我們只要 OK 的具體值就可以了。

針對這兩種處女座訴求, Rust 語言的開發者們在標準庫中定義了兩個幫助函數 unwrap()expect()

方法原型說明
unwrapunwrap(self):T如果 selfOkSome 則返回包含的值。 否則會調用宏 panic!() 并立即退出程序
expectexpect(self,msg:&str):T如果 selfOkSome 則返回包含的值。 否則調用panic!() 輸出自定義的錯誤并退出

expect() 函數用于簡化不希望事情失敗的錯誤情況。而 unwrap() 函數則在返回 OK 成功的情況下,提取返回的實際結果。

unwrap()expect() 不僅能夠處理 Result <T,E> 枚舉,還可以用于處理 Option <T> 枚舉。

fn main(){let result = is_even(10).unwrap();println!("result is {}",result);println!("end of main");
}
fn is_even(no:i32)->Result<bool,String> {if no%2==0 {return Ok(true);} else {return Err("NOT_AN_EVEN".to_string());}
}

編譯運行以上 Rust 代碼,輸出結果如下

thread 'main' panicked at 'called `Result::unwrap()` on 
an `Err` value: "NOT_AN_EVEN"', libcore\result.rs:945:5
note: Run with `RUST_BACKTRACE=1` for a backtrace
11、'_ 匿名生命周期

Rust 2018 允許你明確標記生命周期被省略的地方,對于此省略可能不清楚的類型。 要做到這一點,你可以使用特殊的生命周期'_,就像你可以用語法 let x:_ = ..;明確標記一個類型一樣。

要我們說的話,無論出于什么原因,我們在 &'a str 周圍有一個簡單的封裝:

struct StrWrap<'a>(&'a str);

Rust 版本指南 中文版

3、棧的 Rust 代碼實現、運行結果

stack.rs

/** @Description: * @Author: tianyw* @Date: 2023-12-10 17:43:34* @LastEditTime: 2023-12-10 21:28:31* @LastEditors: tianyw*/
#[derive(Debug)] // Debug 是派生宏的名稱,此語句為 Stack 結構體實現了 Debug traitpub struct Stack<T> { // pub 表示公開的size: usize, // 棧大小data: Vec<T>, // 棧數據 泛型數組
}impl<T> Stack<T> { // impl 用于定義類型的實現,如實現 new 方法、is_empty 方法等// 初始化空棧pub fn new() -> Self { // 指代 Stack 類型Self {size: 0,data: Vec::new() // 初始化空數組}}pub fn is_empty(&self) -> bool {0 == self.size // 結尾沒有分號,表示返回當前值}pub fn len(&self) -> usize { // &self 只可讀self.size // 結尾沒有分號 表示返回當前值}// 清空棧pub fn clear(&mut self) { // &mut self 可讀、可寫self.size = 0;self.data.clear();}// 將數據保存在 Vec 的末尾pub fn push(&mut self, val:T) {self.data.push(val);self.size +=1;}// 在將棧頂減1后,彈出數據pub fn pop(&mut self) -> Option<T> {if 0 == self.size { return None; }self.size -= 1;self.data.pop()}// 返回棧頂數據引用和可變引用pub fn peek(&self) -> Option<&T> {if 0 == self.size {return None;}self.data.get(self.size - 1) // 不帶分號 獲取值并返回}pub fn peek_mut(&mut self) -> Option<&mut T> {if 0 == self.size {return None;}self.data.get_mut(self.size - 1)}// 以下是為棧實現的迭代功能// into_iter:棧改變,成為迭代器// iter: 棧不變,得到不可變迭代器// iter_mut: 棧不變,得到可變迭代器pub fn into_iter(self) -> IntoIter<T> {IntoIter(self)}pub fn iter(&self) -> Iter<T> {let mut iterator = Iter { stack: Vec::new() };for item in self.data.iter() {iterator.stack.push(item);}iterator}pub fn iter_mut(&mut self) -> IterMut<T> {let mut iterator = IterMut { stack: Vec::new() };for item in self.data.iter_mut() {iterator.stack.push(item);}iterator}}// 實現三種迭代功能
pub struct IntoIter<T>(Stack<T>);
impl<T:Clone> Iterator for IntoIter<T> {type Item = T;fn next(&mut self) -> Option<Self::Item> {if !self.0.is_empty() {self.0.size -= 1;self.0.data.pop()} else {None}}
}pub struct Iter<'a,T:'a> { stack: Vec<&'a T>, }
impl<'a,T> Iterator for Iter<'a,T> {type Item = &'a T;fn next(&mut self) -> Option<Self::Item> {self.stack.pop()}
}pub struct IterMut<'a,T:'a> { stack: Vec<&'a mut T> }
impl<'a,T> Iterator for IterMut<'a,T> {type Item = &'a mut T;fn next(&mut self) -> Option<Self::Item> {self.stack.pop()}
}    

main.rs

mod stack;
fn main() {basic();peek();iter();fn basic() {let mut s= stack::Stack::new();s.push(1);s.push(2);s.push(3);println!("size:{},{:?}", s.len(), s);println!("pop {:?},size {}", s.pop().unwrap(), s.len());println!("empty: {}, {:?}", s.is_empty(), s);s.clear();println!("{:?}", s);}fn peek() {let mut s = stack::Stack::new();s.push(1);s.push(2);s.push(3);println!("{:?}", s);let peek_mut = s.peek_mut();if let Some(top) = peek_mut {*top = 4;}println!("top {:?}", s.peek().unwrap());println!("{:?}", s);}fn iter() {let mut s = stack::Stack::new();s.push(1);s.push(2);s.push(3);let sum1 = s.iter().sum::<i32>();let mut addend = 0;for item in s.iter_mut() {*item += 1;addend += 1;}let sum2 = s.iter().sum::<i32>();println!("{sum1} + {addend} = {sum2}");assert_eq!(9, s.into_iter().sum::<i32>());}
}

cargo run 運行結果

在這里插入圖片描述

這里使用集合容器Vec作為棧的底層實現,因為Rust中的Vec提供了有序集合機制和一組操作方法,只需要選定Vec的哪一端是棧頂就可以實現其他操作了。以下棧實現假定Vec的尾部保存了棧的頂部元素,隨著棧不斷增長,新項將被添加到Vec的末尾。因為不知道所插入數據的類型,所以采用泛型數據類型T。此外,為了實現迭代功能,這里添加了IntoIter、Iter、IterMut三個結構體,以分別完成三種迭代功能。

應用:括號匹配、加減乘除優先級匹配

// par_checker3.rsfn par_checker3(par: &str) -> bool {let mut char_list = Vec::new();for c in par.chars() { char_list.push(c); }let mut index = 0;let mut balance = true;let mut stack = Stack::new();while index < char_list.len() && balance {let c = char_list[index];// 將開始符號入棧if '(' == c || '[' == c || '{' == c {stack.push(c);}// 如果是結束符號,則判斷是否平衡if ')' == c || ']' == c || '}' == c {if stack.is_empty() {balance = false;} else {let top = stack.pop().unwrap();if !par_match(top, c) { balance = false; }}}// 非括號字符直接跳過index += 1;}balance && stack.is_empty()
}fn main() {let sa = "(2+3){func}[abc]"; let sb = "(2+3)*(3-1";let res1 = par_checker3(sa); let res2 = par_checker3(sb);println!("sa balanced:{res1}, sb balanced:{res2}");// (2+3){func}[abc] balanced:true, (2+3)*(3-1 balanced:false
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/215400.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/215400.shtml
英文地址,請注明出處:http://en.pswp.cn/news/215400.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

電腦入門基礎知識

1.電腦鍵盤個數一般都是有多少個&#xff1f; 答&#xff1a;一般情況下&#xff0c;電腦鍵盤只有一個。但是&#xff0c;也有一些特殊的情況&#xff0c;例如游戲玩家可能會使用額外的游戲鍵盤&#xff0c;或者一些專業人士可能會使用多個鍵盤來提高工作效率。但是在大多數情…

[Spring~源碼] ControllerAdvice揭秘

在Spring MVC中&#xff0c;我們經常使用ControllerAdvice注解&#xff0c;可以實現全局統一異常處理、全局數據綁定等功能。但是&#xff0c;它的實現原理是什么呢&#xff1f;在本文中&#xff0c;我們將深入探究ControllerAdvice的實現原理。 文章目錄 什么是ControllerAdvi…

docker-compose.yml文件配置詳解

簡介 Compose 是用于定義和運行多容器 Docker 應用程序的工具。通過 Compose&#xff0c;您可以使用 YML 文件來配置應用程序需要的所有服務。然后&#xff0c;使用一個命令&#xff0c;就可以從 YML 文件配置中創建并啟動所有服務。 docker compose文件是一個yaml格式的文件&a…

【Hadoop_04】HDFS的API操作與讀寫流程

1、HDFS的API操作1.1 客戶端環境準備1.2 API創建文件夾1.3 API上傳1.4 API參數的優先級1.5 API文件夾下載1.6 API文件刪除1.7 API文件更名和移動1.8 API文件詳情和查看1.9 API文件和文件夾判斷 2、HDFS的讀寫流程&#xff08;面試重點&#xff09;2.1 HDFS寫數據流程2.2 網絡拓…

學會面向對象經典練習題21道

1.面向對象練習&#xff1a;設計小狗類 需求&#xff1a; 抽象形成一個小狗類Dog 屬性&#xff1a;名字name 年齡age 品種kind 主人host 價格price 功能&#xff1a; 跑run&#xff1a;無參&#xff0c;打印&#xff1a;小狗Dog跑的老快了~ 吃eat&#xff1a;參數int n&#x…

當MongoDB主鍵為String時,mongoTemplate無法根據id查詢的問題

MongoDB推薦使用ObjectId作為主鍵&#xff0c;但國內的開發都知道&#xff0c;事情往往不如人所愿&#xff0c;當我們真的出現了“_id”主鍵的類型為String時&#xff0c;且還必須想用mongoTemplate.findOne或findList時&#xff0c;直接使用該方法會導致查詢結果為空。 因為m…

https 協議

目錄 加密方式 對稱加密 非對稱加密 非對稱加密 非對稱加密 非對稱加密 對稱加密 AC證書 AC證書內容 數據摘要 數據簽名 在我們前面學習的http協議里面&#xff0c;我們發送的內容都是明文傳輸的&#xff0c;所以在安全上并不安全&#xff0c;但是在現在信息發達的時…

Java高級技術:優化性能與擴展性的最佳實踐

標題&#xff1a;Java高級技術&#xff1a;優化性能與擴展性的最佳實踐 摘要&#xff1a;本文將介紹Java中一些高級技術&#xff0c;以提高性能和代碼的擴展性。本文不包括反射和并發編程&#xff0c;旨在幫助開發者進一步提升Java應用程序的質量和可維護性。 優化性能的最佳實…

面試題目總結(三)

1. Spring、Springboot、springMVC、Spring Cloud 的區別&#xff1a; Spring&#xff1a;Spring 是一個開源的、輕量級的Java框架&#xff0c;提供了豐富的功能和組件&#xff0c;用于構建企業級應用程序。Spring框架包含了很多模塊&#xff0c;包括核心容器、數據訪問、事物…

MATLAB算法實戰應用案例精講-【數模應用】漫談機器學習(七)

目錄 幾個高頻面試題目 機器學習算法工程師需要掌握哪些編程語言? 1.Python 2. C# 3.JavaScript 4. R 5.Java

Linux之Apache服務器安裝及配置

一、Apache服務器簡介 Apache HTTP Server&#xff08;簡稱Apache&#xff09;是Apache軟件基金會的一個開放源碼的網頁服務器&#xff0c;可以在大多數計算機操作系統中運行&#xff0c;由于其多平臺和安全性被廣泛使用。Apache曾經是世界使用排名第一的Web服務器軟件&#xf…

VSCODE連接遠程服務器

安裝ssh插件 根據你的操作系統選擇對應的版本進行下載和安裝。 安裝完成之后&#xff0c;啟動vscode&#xff0c;選擇左側Extensions 選項卡&#xff0c;在輸入框搜索 remote &#xff0c;選擇安裝Remote-SSH插件。 安裝完成之后會在左側新增一個選項卡Remote Explorer&#xf…

肥貓游戲報價器|計價器|王者榮耀代練陪練等游戲報價器軟件介紹說明

目錄 1. 前言2. 軟件著作權3. 軟件使用說明3.1 進入軟件3.2 用戶登錄3.3 首頁3.4 報價器3.4.1 總體介紹3.4.2 王者報價器3.4.3 LOL手游報價器3.4.4 英雄聯盟報價器3.4.5 云頂之弈報價器3.4.7 王者水晶報價器3.4.8 和平精英報價器3.4.9 蛋仔派對報價器3.4.10 穿越火線報價器3.4.…

kafka學習筆記--broker工作流程、重要參數

本文內容來自尚硅谷B站公開教學視頻&#xff0c;僅做個人總結、學習、復習使用&#xff0c;任何對此文章的引用&#xff0c;應當說明源出處為尚硅谷&#xff0c;不得用于商業用途。 如有侵權、聯系速刪 視頻教程鏈接&#xff1a;【尚硅谷】Kafka3.x教程&#xff08;從入門到調優…

Linux mc命令教程:如何有效地使用mc命令(附案例詳解和注意事項)

Linux mc命令介紹 mc命令是Linux中的一個視覺文件管理器&#xff0c;全稱為Midnight Commander。它提供了一個用戶友好的界面&#xff0c;使得在Linux環境中的文件和目錄管理變得更加直觀和方便。mc命令支持鼠標操作和顏色顯示&#xff0c;同時也提供了一套菜單接口&#xff0…

TypeScript 常用高級類型

目錄 前言&#xff1a; TypeScript 常用高級類型 基本概念 高級類型 1. 交叉類型&#xff08;Intersection Types&#xff09; 2. 聯合類型&#xff08;Union Types&#xff09; 3. 映射類型&#xff08;Mapped Types&#xff09; 4. 條件類型&#xff08;Conditional…

GGML 或GGUF的14種不同量化模式說明

查看 TheBloke/Llama-2–13B-chat-GGML 存儲庫中的文件&#xff0c;我們可以看到 14 種不同的 GGML 模型&#xff0c;對應于不同類型的量化。它們遵循特定的命名約定&#xff1a;“q” 用于存儲權重的位數&#xff08;精度&#xff09; 特定變體。以下是所有可能的量化方法及其…

Pytorch-Transformer軸承故障一維信號分類(三)

目錄 前言 1 數據集制作與加載 1.1 導入數據 第一步&#xff0c;導入十分類數據 第二步&#xff0c;讀取MAT文件驅動端數據 第三步&#xff0c;制作數據集 第四步&#xff0c;制作訓練集和標簽 1.2 數據加載&#xff0c;訓練數據、測試數據分組&#xff0c;數據分batch…

據房間Id是否存在,判斷當前房間是否到期且實時更改顏色

重點代碼展示&#xff1a; <template><el-col style"width: 100%;height: 100%;"><el-col :span"20"><el-card class"room_info"><avue-data-icons :option"option"></avue-data-icons></el-…

RT-DETR算法優化改進:輕量化自研設計雙卷積重新設計backbone和neck,完成漲點且計算量和參數量顯著下降

??????本文自研創新改進:雙卷積由組卷積和異構卷積組成,執行 33 和 11 卷積運算代替其他卷積核僅執行 11 卷積,YOLOv8 Conv,從而輕量化RT-DETR,性能如下表,GFLOPs 8.1降低至7.6,參數量6.3MB降低至5.8MB RT-DETR魔術師專欄介紹: https://blog.csdn.net/m0_637742…