單向循環鏈表與雙向鏈表

單向循環鏈表的原理與應用

思考:對于單向鏈表而言,想要遍歷鏈表,則必須從鏈表的首結點開始進行遍歷,請問有沒有更簡單的方案實現鏈表中的數據的增刪改查?

回答:是有的,可以使用單向循環的鏈表進行設計,單向循環的鏈表的使用規則和普通的單向鏈表沒有較大的區別,需要注意:單向循環鏈表的尾結點的指針域中必須指向鏈表的首結點的地址,由于帶頭結點的單向循環鏈表更加容易進行管理,所以教學以帶頭結點的為例:

上圖所示的就是一個典型的單向循環鏈表的結構,可以發現單向循環鏈表的結構屬于環形結構,鏈表中的最后一個結點的指針域中存儲的是鏈表的第一個結點的地址。

為了管理單向循環鏈表,需要構造頭結點的數據類型以及構造有效結點的數據類型,如下:

//指的是單向循環鏈表中的結點有效數據類型,用戶可以根據需要進行修改
typedef int  DataType_t;//構造單向循環鏈表的結點,鏈表中所有結點的數據類型應該是相同的
typedef struct CircularLinkedList
{DataType_t  		 data; //結點的數據域struct LinkedList	*next; //結點的指針域}CircLList_t;

創建一個空鏈表,由于是使用頭結點,所以就需要申請頭結點的堆內存并初始化即可!

//創建一個空單向循環鏈表,空鏈表應該有一個頭結點,對鏈表進行初始化
CircLList_t * CircLList_Create(void)
{//1.創建一個頭結點并對頭結點申請內存CircLList_t *Head = (CircLList_t *)calloc(1,sizeof(CircLList_t));if (NULL == Head){perror("Calloc memory for Head is Failed");exit(-1);}//2.對頭結點進行初始化,頭結點是不存儲數據域,指針域指向自身,體現“循環”思想Head->next = Head;//3.把頭結點的地址返回即可return Head;
}

?

創建新結點,為新結點申請堆內存并對新結點的數據域和指針域進行初始化,操作如下:

//創建新的結點,并對新結點進行初始化(數據域 + 指針域)
CircLList_t * CircLList_NewNode(DataType_t data)
{//1.創建一個新結點并對新結點申請內存CircLList_t *New = (CircLList_t *)calloc(1,sizeof(CircLList_t));if (NULL == New){perror("Calloc memory for NewNode is Failed");return NULL;}//2.對新結點的數據域和指針域進行初始化New->data = data;New->next = NULL;return New;
}

?遍歷整個鏈表

//遍歷鏈表
bool CircLList_Print(CircLList_t *Head)
{//對單向循環鏈表的頭結點的地址進行備份CircLList_t *Phead = Head;//判斷當前鏈表是否為空,為空則直接退出if (Head->next == Head){printf("current linkeflist is empty!\n");return false;}//從首結點開始遍歷while(Phead->next){//把頭結點的直接后繼作為新的頭結點Phead = Phead->next;//輸出頭結點的直接后繼的數據域printf("data = %d\n",Phead->data);//判斷是否到達尾結點,尾結點的next指針是指向首結點的地址if (Phead->next == Head->next){break;}	}return true;
}

?根據情況把新結點插入到鏈表中,此時可以分為尾部插入、頭部插入、指定位置插入:

頭插

bool CircLList_HeadInsert(CircLList_t *Head, DataType_t data)
{CircLList_t *Phead = Head; //備份頭結點的地址//1.創建新的結點,并對新結點進行初始化CircLList_t *New = CircLList_NewNode(data);if (NULL == New){printf("can not insert new node\n");return false;}//2.判斷鏈表是否為空,如果為空,則把新結點作為首結點,體現“循環”if (Head->next == Head){Head->next = New;New->next = New;return true;}//3.如果鏈表是非空的,則需要對尾結點的next指針進行處理,指向首結點while(Phead->next){Phead = Phead->next;if ( Phead->next == Head->next ){break;}}Phead->next = New;        //尾結點的next指針指向新的首結點New->next = Head->next;   //新結點的next指針指向原本的首結點Head->next = New;         //更新首結點地址,讓頭結點的next指針指向新結點return true;
}

?尾插

bool CircLList_TailInsert(CircLList_t *Head, DataType_t data)
{CircLList_t *Phead = Head; //備份頭結點的地址//1.創建新的結點,并對新結點進行初始化CircLList_t *New = CircLList_NewNode(data);if (NULL == New){printf("can not insert new node\n");return false;}//2.判斷鏈表是否為空,如果為空,則把新結點作為首結點,體現“循環”if (Head->next == Head){Head->next = New;New->next = New;return true;}//3.如果鏈表是非空的,則需要對尾結點的next指針進行處理,指向首結點while(Phead->next){Phead = Phead->next;if ( Phead->next == Head->next ){break;}}Phead->next = New;      //舊的尾結點的next指針指向新結點New->next = Head->next; //新結點的next指針指向首結點地址return true;
}

指定位置后插入

bool CircLList_TailInsert(CircLList_t *Head, DataType_t data)
{CircLList_t *Phead = Head; //備份頭結點的地址//1.創建新的結點,并對新結點進行初始化CircLList_t *New = CircLList_NewNode(data);if (NULL == New){printf("can not insert new node\n");return false;}//2.判斷鏈表是否為空,如果為空,則把新結點作為首結點,體現“循環”if (Head->next == Head){Head->next = New;New->next = New;return true;}//3.如果鏈表是非空的,則需要對指定位置結點的指針進行處理while (Phead->next){if (Phead->data == Data) {New->next = Phead->next;Phead->next = New;return true;}Phead = Phead->nextif(Phead == Head->next)break;Phead = Phead->next;}
}

根據情況可以從鏈表中刪除某結點,此時可以分為尾部刪除、頭部刪除、指定元素刪除:

頭刪

//頭刪
bool LList_HeadDel(LList_t *Head)
{//對單向循環鏈表的頭結點的地址進行備份CircLList_t *Phead = Head;//對單向循環鏈表的首結點的地址進行備份CircLList_t *Temp = Head->next;//2.判斷鏈表是否為空,如果為空,則退出if (Head->next == Head){printf("Linkedlist is Empty\n");return false;}//3.判斷鏈表中是否只有首結點if ( Head->next == Head->next->next ){Temp->next = NULL;           //首結點的next指針指向NULLHead->next = Head;           //頭結點的next指針指向頭結點,體現“循環”free(Temp);                  //釋放結點內存return true;}    //4.如果鏈表是非空的,則需要對尾結點的next指針進行處理,指向新的首結點while(Phead->next){Phead = Phead->next;if ( Phead->next == Temp )   //遍歷到尾結點{break;}}Phead->next = Temp->next ;       //讓尾結點的next指針指向新的首結點Head->next = Phead->next;        //更新首結點,讓頭結點的next指針指向新的首結點Temp->next = NULL;               //舊的首結點的next指針指向NULL,從鏈表中斷開free(Temp);                      //釋放待刪除結點的內存return true;
}

尾刪

//頭刪
bool LList_HeadDel(LList_t *Head)
{//對單向循環鏈表的頭結點的地址進行備份CircLList_t *Phead = Head;//對單向循環鏈表的首結點的地址進行備份CircLList_t *Temp = Head->next;//2.判斷鏈表是否為空,如果為空,則退出if (Head->next == Head){printf("Linkedlist is Empty\n");return false;}//3.判斷鏈表中是否只有尾結點if ( Head->next == Head->next->next ){Temp->next = NULL;           //首結點的next指針指向NULLHead->next = Head;           //頭結點的next指針指向頭結點,體現“循環”free(Temp);                  //釋放結點內存return true;}    //4.如果鏈表是非空的,則需要對尾結點的next指針進行處理,指向新的首結點while(Phead->next){Phead_prv = Phead            //保存尾結點直接前驅的地址Phead = Phead->next;if ( Phead->next == Temp )   //遍歷到尾結點{break;}}Phead_prv->next = Temp ;          //讓尾結點的直接前驅指向首節點Phead->next = NULL;               //尾結點的next指針指向NULL,從鏈表中斷開free(Phead);                      //釋放待刪除結點的內存return true;
}

指定刪

雙向鏈表的原理與應用

如果想要提高單向鏈表或者單向循環鏈表的訪問速度,則可以在鏈表中的結點中再添加一個指針域,讓新添加的指針域指向當前結點的直接前驅的地址,也就意味著一個結點中有兩個指針域(prev + next),也被稱為雙向鏈表(Double Linked List)。?

由于帶頭結點更加方便用戶進行數據訪問,所以本次創建一條帶頭結點的雙向不循環的鏈表。

//指的是雙向鏈表中的結點有效數據類型,用戶可以根據需要進行修改
typedef int  DataType_t;//構造雙向鏈表的結點,鏈表中所有結點的數據類型應該是相同的
typedef struct DoubleLinkedList
{DataType_t  		     data; //結點的數據域struct DoubleLinkedList	*prev; //直接前驅的指針域struct DoubleLinkedList	*next; //直接后繼的指針域}DoubleLList_t;

創建一個空鏈表,由于是使用頭結點,所以就需要申請頭結點的堆內存并初始化即可!

//創建一個空雙向鏈表,空鏈表應該有一個頭結點,對鏈表進行初始化
DoubleLList_t * DoubleLList_Create(void)
{//1.創建一個頭結點并對頭結點申請內存DoubleLList_t *Head = (DoubleLList_t *)calloc(1,sizeof(DoubleLList_t));if (NULL == Head){perror("Calloc memory for Head is Failed");exit(-1);}//2.對頭結點進行初始化,頭結點是不存儲數據域,指針域指向NULLHead->prev = NULL;Head->next = NULL;//3.把頭結點的地址返回即可return Head;
}

創建新結點,為新結點申請堆內存并對新結點的數據域和指針域進行初始化,操作如下:

DoubleLList_t * DoubleLList_NewNode(DataType_t data)
{//1.創建一個新結點并對新結點申請內存DoubleLList_t *New = (DoubleLList_t *)calloc(1,sizeof(DoubleLList_t));if (NULL == New){perror("Calloc memory for NewNode is Failed");return NULL;}//2.對新結點的數據域和指針域(2個)進行初始化New->data = data;New->prev = NULL;New->next = NULL;return New;
}

根據情況可以從鏈表中插入新結點,此時可以分為尾部插入、頭部插入、指定位置插入:

頭插

//頭插
bool DoubleList_HeadInsert(DoubleList_t * Head, DataType_t data)
{//1.創建新結點并對新結點進行初始化DoubleList_t * New = DoubleList_NewNode(data);if (NULL == New){printf("can not insert new node\n");return false;}//2.判斷雙向鏈表是否為空,如果為空,則直接插入到頭結點之后if (NULL == Head->next){Head->next = New;  //讓頭結點的next指針指向新結點return true;}//3.如果雙向鏈表為非空,則把新結點插入到鏈表的頭部New->next = Head->next; //新結點的next指針指向原本的首結點地址Head->next->prev = New; //原本的首結點的prev指針指向新結點的地址Head->next = New; //更新頭結點的next指針,讓next指針指向新結點的地址return true;
}

尾插

//尾插
bool DoubleList_TailInsert(DoubleList_t * Head, DataType_t data)
{DoubleList_t * Phead = Head; //備份頭結點地址,防止頭結點丟失//1.創建新結點并對新結點進行初始化DoubleList_t * New = DoubleList_NewNode(data);if (NULL == New){printf("can not insert new node\n");return false;}//2.判斷雙向鏈表是否為空,如果為空,則直接插入到頭結點之后if (NULL == Head->next){Head->next = New; //讓頭結點的next指針指向新結點return true;}//3.如果雙向鏈表為非空,則把新結點插入到鏈表的尾部while(Phead->next){Phead = Phead->next;}Phead->next = New; //尾結點的next指針指向新結點地址New->prev = Phead; //新結點的prev指針指向原本的尾結點地址return true;
}

指定插

根據情況可以從鏈表中刪除某結點,此時可以分為尾部刪除、頭部刪除、指定結點刪除:

//指定位置插入 插入目標結點之后
bool DoubleList_DestInsert(DoubleList_t *Head, DataType_t destval, DataType_t data)
{DoubleList_t * Phead = Head; //備份頭結點地址,防止頭結點丟失//1.創建新結點并對新結點進行初始化DoubleList_t * New = DoubleList_NewNode(data);if (NULL == New){printf("can not insert new node\n");return false;}//2.判斷雙向鏈表是否為空,如果為空,則直接插入到頭結點之后if (NULL == Head->next){Head->next = New; //讓頭結點的next指針指向新結點return true;}//3.如果雙向鏈表為非空,此時分為3種情況(尾部 or 中間)while(Phead->next){Phead = Phead->next;if (Phead->data == destval){break;}}//如果遍歷鏈表之后發現沒有目標結點,則退出即可if (Phead->next == NULL && Phead->data != destval){printf("dest node is not found\n");return false;}//如果遍歷鏈表找到目標結點,則分為(尾部 or 中間)if(Phead->next == NULL)      //尾插{New->prev   = Phead;     //新結點的prev指針指向尾結點的地址Phead->next = New;       //尾結點的next指針指向新結點}else                         //中間{New->next = Phead->next;     // 新結點的next指針指向目標結點的直接后繼結點New->prev = Phead;           // 新結點的prev指針指向目標結點的地址Phead->next->prev = New;     // 目標結點的直接后繼結點的prev指針指向新結點Phead->next = New;           // 目標結點的next指針指向新結點}return true;
}

頭刪

//頭刪
bool DoubleList_HeadDel(DoubleList_t *Head)
{//對雙向鏈表的首結點的地址進行備份DoubleList_t *Temp = Head->next;//2.判斷鏈表是否為空,如果為空,則退出if (Head->next == NULL){printf("DoubleList is Empty\n");return false;}//3.判斷鏈表中是否只有首結點if (Temp->next != NULL)          // 如果鏈表不止一個節點{         Temp->next->prev = NULL;     // 新首節點的prev置為NULL}//4.如果鏈表是非空的,則需要對頭結點的next指針進行處理,指向新的首結點Head->next = Temp->next;         //頭結點的next指針進行處理,指向新的首結點Temp->next = NULL;               //舊的首節點next指向NULLfree(Temp);                      //釋放待刪除結點的內存return true;
}

?如果沒有 if (Thead->next != NULL) 這個條件判斷,直接寫 Thead->next->prev = NULL ,會產生以下嚴重后果:當只有一個結點時, Thead->next 的值為 NULL 。因為尾節點的 next 指針指向 NULL ,表示鏈表結束。如果直接執行Thead->next->prev = NULL ,就相當于對一個空指針進行解引用操作,去訪問它的成員 prev 。在 C 語言中,這是不允許的,會導致程序崩潰,拋出類似 “Segmentation fault(段錯誤)” 這樣的運行時錯誤。?

尾刪

// 尾刪
bool DoubleList_TailDel(DoubleList_t *Head)
{// 備份頭結點的地址DoubleList_t *Phead = Head;// 判斷鏈表是否為空,如果為空則退出if (Head->next == NULL){printf("DoubleList is Empty\n");return false;}// 遍歷到尾結點while (Phead->next != NULL){Phead = Phead->next;}// 獲取尾結點的前驅結點DoubleList_t *Prev = Phead->prev;// 如果存在前驅結點(即鏈表不止一個節點)if (Prev != NULL){Prev->next = NULL;  // 前驅結點的next指向NULL}else{Head->next = NULL;  // 如果無前驅,說明刪除后鏈表為空}// 釋放尾結點內存free(Phead);return true;
}

指定刪

//指定刪除
bool DoubleList_DestDel(DoubleList_t * Head, DataType_t destval)
{DoubleList_t * Phead = Head; //備份頭結點地址,防止頭結點丟失//1.判斷雙向鏈表是否為空,如果為空,則刪除失敗if (NULL == Head->next){printf("linked list is empty\n");return false;}//2.如果雙向鏈表為非空,此時遍歷鏈表查找沒有目標結點while(Phead->next){Phead = Phead->next;if (Phead->data == destval){break;}}//如果鏈表中沒有目標結點,此時直接退出即可if (Phead->next == NULL && Phead->data != destval){printf("dest node is not found\n");return false;}//如果鏈表中發現目標結點,此時分為(頭部 or 尾部 or 中間)if(Phead == Head->next)                 //頭部{Head->next = Phead->next;           //更新頭結點,讓頭結點的next指針指向首結點的直接后繼if (Phead->next != NULL)            //如果待刪除節點的下一個節點存在,則將其 prev 置為 NULL,確保新頭節點的前驅正確。{Phead->next->prev = NULL;}Phead->next = NULL;free(Phead);                        //釋放待刪除結點內存}else if(Phead->next == NULL)            //尾部{Phead->prev->next = NULL;           //尾結點的直接前驅結點的next指針指向NULLPhead->prev = NULL;                 //尾結點的prev指針指向NULLfree(Phead);                        //釋放待刪除結點內存}else                                    //中間{Phead->prev->next = Phead->next;    //讓待刪除結點的直接前驅結點的next指針指向待刪除結點的直接后繼Phead->next->prev = Phead->prev;    //讓待刪除結點的直接后繼結點的prev指針指向待刪除結點的直接前驅地址Phead->next = NULL;                 //讓待刪除結點的next指針指向NULLPhead->prev = NULL;                 //讓待刪除結點的prev指針指向NULLfree(Phead);                        //釋放待刪除結點內存}return true;
}

練習題

?

A :雙鏈表在插入和刪除時,需要同時調整前驅和后繼指針,操作并不比單鏈表簡單,所以 A 選項錯誤。

B:單鏈表和雙鏈表都不支持隨機訪問

C:雙鏈表無論是表頭指針還是表尾指針都很重要,都不能省略,因為雙鏈表的遍歷、插入和刪除等操作往往需要借助表頭指針或表尾指針來進行定位起始位置等操作\

D:單鏈表中每個結點只有一個指向后繼的指針,若要訪問前驅結點,只能從頭開始遍歷鏈表。而雙鏈表的每個結點既有指向后繼的指針,又有指向前驅的指針 ,可以方便靈活地訪問前后相鄰結點,所以 D 選項正確。

A:p->next=q;?這一步執行后,p?原來的后繼結點就丟失了,后續再執行?q->next=p->next;?無法正確設置?q?的后繼

B:操作順序符合上述在雙向鏈表中?p?結點后插入?q?結點的步驟,要記住插入動作要先連接在斷開
C:同 A
D:同 A

A:p->prior=q;?這一步直接改變?p?的前驅,后續?p->prior->next=q;?操作時,由于?p?的前驅已經改變,會導致邏輯錯誤

B:p->prior=q->next;?這里邏輯混亂,q->next?指向的是?p?,將其賦給?p->prior?不符合在?p?前插入?q?的指針調整邏輯

C:q->next=p; p->next=q;?這兩步操作錯誤,在雙向鏈表中在?p?前插入?q?,不應該改變?p?的后繼,且后續指針調整邏輯也混亂

D:對

A:對

B:p->prior = p->prior->prior;?這一步將?p?的前驅指向了?p?前驅的前驅,邏輯混亂;p->prior->prior = p;?也不符合雙向鏈表刪除結點的指針調整規則,會導致鏈表結構錯誤
C:p->next->prior = p;?這一步錯誤地將?p?后繼的前驅又指向了?p?,沒有達到刪除?p?的目的;p->next = p->next->next;?也不能正確調整指針
D:p->next = p->prior->prior;?和?p->prior = p->prior->prior;?這兩步操作不符合雙向鏈表刪除結點時調整指針的邏輯,會使鏈表結構出錯

A:順序表:它可以通過數組下標直接隨機存取任一指定序號的元素,時間復雜度為O(1)?。在順序表最后進行插入和刪除運算時,若不涉及擴容等操作 ,插入和刪除的時間復雜度也較低,插入平均時間復雜度為 O(1)(不考慮擴容) ,刪除平均時間復雜度為 O(1)(不考慮元素移動后的整理等額外操作),所以順序表能滿足最常用操作的高效需求。

B:雙鏈表:雙鏈表不支持隨機存取,要存取指定序號的元素,需要從表頭或表尾開始遍歷,時間復雜度為?O(n)

C:雙循環鏈表:和雙鏈表類似,不支持隨機存取,存取指定序號元素需遍歷,時間復雜度為?O(n)?

D:單循環鏈表:同樣不支持隨機存取,存取指定序號元素要遍歷鏈表,時間復雜度為 O(n)

A:單鏈表:在單鏈表中,在最后一個元素之后插入元素,需要遍歷整個鏈表找到尾節點,時間復雜度為?O(n)?;刪除第一個元素,雖然時間復雜度為?O(1),但插入操作效率低,不滿足最常用操作高效的要求。

B:不帶頭結點的單循環鏈表:插入最后一個元素需要遍歷鏈表找尾節點,時間復雜度?O(n)?;刪除第一個元素時,因為沒有頭結點輔助,還需要先找到尾節點使其?next?指向第二個節點,操作相對復雜,時間復雜度也較高,整體不滿足要求。

C:雙鏈表:在雙鏈表中,刪除第一個元素時間復雜度為?O(1),但在最后一個元素之后插入元素,需要遍歷鏈表找到尾節點(雖然可以從表頭或表尾雙向遍歷,但仍需一定時間),時間復雜度為?O(n)?,不是最節省時間的。

D:不帶頭結點且有尾指針的單循環鏈表:有尾指針,在最后一個元素之后插入元素時,可直接利用尾指針,時間復雜度為?O(1);刪除第一個元素時,可通過尾指針找到第一個元素(尾指針的?next?指向第一個元素),然后調整指針完成刪除,時間復雜度也為?O(1)?,能高效滿足最常用的兩種操作,最節省運算時間。

A:在順序表中,由于元素是連續存儲的,可通過數組下標直接訪問第i個元素,時間復雜度為O(1)。

B:效率一樣
C:效率一樣
???????D:效率一樣

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

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

相關文章

Windows鼠標掉幀測試與修復

前言 這兩天突然發現鼠標似乎有掉幀,但是掉的又不太明顯,用著感覺似乎快速移動的時候會有一瞬間卡一下,但是眼睛又看不清楚,不太確定是不是自己的心理作用,非常難受。 如何判斷鼠標是否掉幀 根據我的經驗&#xff0…

U 盤數據恢復全攻略

目錄 💾 U盤數據誤刪怎么辦?兩款實用工具助你找回丟失文件!1?? Recover My Files:數據恢復的得力助手📌 主要特點🛠 使用步驟詳解1. 下載與安裝2. 啟動軟件并選擇恢復類型3. 選擇U盤所在分區4. 選擇文件恢…

HarmonyOS NEXT~鴻蒙系統運維:全面解析與最佳實踐

HarmonyOS NEXT~鴻蒙系統運維:全面解析與最佳實踐 摘要 本文深入探討鴻蒙(HarmonyOS)系統的運維管理,從架構特點到日常維護操作,全面分析這一全場景分布式操作系統的運維要點。文章將介紹鴻蒙系統特有的分布式能力運維管理、性能…

基于 STM32 的智慧農業溫室控制系統設計與實現

摘要 本文提出一種基于 STM32 微控制器的智慧農業溫室控制系統設計方案,通過集成多類型環境傳感器、執行機構及無線通信模塊,實現對溫室內溫濕度、光照、土壤濕度等參數的實時監測與自動調控。文中詳細闡述硬件選型、電路連接及軟件實現流程,并附關鍵代碼示例,為智慧農業領…

Appium+python自動化(五)- 模擬器

簡介 Appium是做安卓自動化的一個比較流行的工具,對于想要學習該工具但是又局限于沒 android 手機來說,可以通過安卓模擬器來解決該問題,下面就講解使用appium連接安卓模擬器的操作步驟。而是由于手機數據線問題,也只好先用模擬器…

汽車充電樁專用ASCP210系列電氣防火限流式保護器

1.概述汽車充電樁專用電氣防火限流式保護器 電氣防火限流式保護器可有效克服傳統斷路器、空氣開關和監控設備存在的短路電流大、切斷短路電流時間長、短路時產生的電弧火花大,以及使用壽命短等弊端,發生短路故障時,能以微秒級速度快速限制短…

Linux中磁盤分區與掛載

一、磁盤劃分 1.1 了解磁盤 硬盤的接口類型 接口類型發展方向應用場景IDESATA I/II/III個人PC機SCSISAS服務器上 磁盤命名規則 OSIDE(并口)SATA(串口)SCSIRHEL5/dev/hda/dev/sda/dev/sdaRHEL6/dev/sda/dev/sda/dev/sdaRHEL7/dev/sda/dev/sda/dev/sda 1.2 磁盤劃分 磁盤劃…

【數據分析】什么是特征蒸餾?

引言 —— “ 在數據洪流中提煉真金——解密特征蒸餾的藝術。” 在數據爆炸的時代,我們每天產生的信息量已遠超人類處理能力的極限。當企業擁有百萬維的用戶行為數據,醫療研究者面對TB級的基因測序記錄,工程師試圖從千萬張圖像中識別關鍵模式…

機器學習筆記【Week4】

一、 為什么要用神經網絡? 邏輯回歸只能處理線性可分問題。例如,經典的 XOR 異或問題無法用單層邏輯回歸準確分類。神經網絡通過多層結構和非線性激活函數,能學習復雜的決策邊界,解決非線性問題。 二、神經網絡的基本組成 神經網…

java交易所,多語言,外匯,黃金,區塊鏈,dapp類型的,支持授權,劃轉,挖礦(源碼下載)

目前這套主要是運營交易所類型的,授權的會貴點,編譯后的是可以直接跑的,圖片也修復了,后門也掃了 都是在跑的項目支持測,全開源 源碼下載:https://download.csdn.net/download/m0_66047725/90887047 更多…

2025CCPC河北省賽題解

題目區分度不錯&#xff0c;不過兩題手快銅確實沒想到。 Attention is all you need&#xff01; H - What is all you need? 簽到題 #include <bits/stdc.h> #define x first #define y second #define int long long #define double long doubleusing namespace st…

【IOS】【OC】【應用內打印功能的實現】如何在APP內實現打印功能,連接本地打印機,把想要打印的界面打印成圖片

【IOS】【OC】【應用內打印功能的實現】如何在APP內實現打印功能&#xff0c;連接本地打印機&#xff0c;打印想打印的界面 設備/引擎&#xff1a;Mac&#xff08;14.1.1&#xff09;/cocos 開發工具&#xff1a;Xcode 開發語言&#xff1a;OC/C 開發需求&#xff1a;工程中…

AWS WebRTC:獲取信令服務節點和ICE服務節點

建立WebRTC的第一步是獲取信令服務節點和ICE服務節點。 前提條件是有訪問AWS的密鑰&#xff0c;主要是ak&#xff0c;sk&#xff0c;token&#xff0c;我這邊是業務云有接口可以返回這些信息&#xff0c;所以我直接從業務云獲取。 先介紹一下什么是ak&#xff0c;sk&#xff…

C++23 新成員函數與字符串類型的改動

文章目錄 引言std::basic_string::contains 與 std::basic_string_view::contains (P1679R3)功能介紹示例代碼優勢 禁止從 nullptr 構造 std::basic_string 和 std::basic_string_view (P2166R1)背景改動影響 std::basic_string_view 的顯式范圍構造函數 (P1989R2)功能介紹示例…

VMware-MySQL主從

MySQL主從 服務器信息 服務器類型角色主機地址主機名稱虛擬機master192.168.40.128test-1虛擬機slave192.168.40.129test-2 Master 配置&#xff08;192.168.40.128&#xff09; 刪除自動生成的配置 /var/lib/mysql/auto.cnf [roottest-1 ~]# rm -rf /var/lib/mysql/auto.…

Java組合、聚合與關聯:核心區別解析

在Java中&#xff0c;組合、聚合和關聯是描述類之間關系的三種不同方式&#xff0c;它們的核心區別在于對象間的依賴強度和生命周期管理。以下是它們的詳細對比&#xff1a; 1. 關聯&#xff08;Association&#xff09; 定義&#xff1a;最基本的類間關系&#xff0c;表示一個…

如何保護網絡免受零日漏洞攻擊?

零日漏洞&#xff08;Zero-Day Vulnerability&#xff09;是指軟件或系統中尚未被廠商發現或修補的安全漏洞。這個名稱中的“零日”意味著&#xff0c;從漏洞被發現到廠商發布修復補丁的時間是零天&#xff0c;也就是說&#xff0c;黑客可以利用這個漏洞進行攻擊&#xff0c;而…

linux快速入門-VMware安裝linux,配置靜態ip,使用服務器連接工具連接,快照和克隆以及修改相關配置信息

安裝VMWare 省略&#xff0c;自己檢索 安裝操作系統-linux 注意&#xff1a;需要修改的我會給出標題&#xff0c;不要修改的直接點擊下一步就可以 選擇自定義配置 選擇稍后安裝操作系統 選擇合適的內存 選擇NAT模式 僅主機模式 虛擬機只能和主機通信&#xff0c;不能上網…

Nest全棧到失業(一):Nest基礎知識掃盲

Nest 是什么? 問你一個問題,node是不是把js拉出來瀏覽器環境運行了?當然,他使用了v8引擎加上自己的底層模塊從而實現了,在外部編輯處理文件等;然后它使用很多方式來發送請求是吧,你知道的什么http.request 或 https.request; 我們瀏覽器中,使用AJAX以及封裝AJAX和http的Axios…

Streamlit 項目知識點總結

目錄 1. 單選框、下拉框格式化 2. 多媒體資源的引用 2.1 搭建一個簡易的http服務器 2.2 約定多媒體資源的輸入格式 2.3 解析多媒體資源 3. 設置頁面的全局背景圖片 4. 輸出流式文本&#xff08;類似打字效果&#xff09; 4.1 使用內置的 st.write_stream 方法實現 4.2…