您好,登錄后才能下訂單哦!
今天小編給大家分享一下C語言線性表鏈式表示及實現的方法的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
線性表的順序表示指的是用一組地址連續的存儲單元依次存儲線性表的數據元素,而線性表的鏈式存儲特點則是用一組任意的存儲單元存儲線性表的數據元素。這組存儲單元既可以是連續的,也可以是不連續的。
對于鏈式存儲的每個數據元素而言,除了存儲其本身的信息之外,還需要存儲一個指示其直接后繼的信息,即直接后繼的存儲位置。這兩部分信息組成了數據元素的存儲映像,稱為結點。
鏈式存儲的結構包含兩個域:一個用于存儲數據元素的信息,另一個用于存儲直接后繼的存儲位置;存儲數據元素信息的域稱為數據域,存儲直接后繼存儲位置的域稱為指針域。
圖示:
數據結構中,在單鏈表的開始結點之前一般要附設一個類型相同的結點,稱之為頭結點。頭結點的數據域可以不存儲任何信息,頭結點的指針域存儲指向開始結點的指針,即第一個元素結點的存儲位置。
附設頭結點的作用:
防止單鏈表是空的而設的。當鏈表為空的時候,帶頭結點的頭指針就指向頭結點,如果當鏈表為空的時候,單鏈表沒有帶頭結點,那么它的頭指針就為NULL
方便單鏈表的特殊操作,插入在表頭或者刪除第一個結點,加入頭結點的話就可以保持單鏈表操作的統一性
當單鏈表加上頭結點之后,無論單鏈表是否為空,頭指針始終指向頭結點,因此空表和非空表的處理也就統一了,方便了單鏈表的操作,也減少了程序的復雜性和出現bug的機會
鏈式表示要實現的功能:
實現工具:Dev C++
構造一個空的頭結點
對線性表進行賦值
對線性表進行銷毀
對線性表進行重置
判斷線性表是否為空
獲取線性表的長度
獲取線性表某一位置對應的元素
在線性表某一位置插入元素
刪除線性表某一位置的元素
求線性表某一元素的前驅
求線性表某一元素的后繼
打印線性表
退出
準備工作:
打開Dev C++后新建一個Source File文件即可 File>new>Source File
在實現線性表的鏈式存儲時導入的頭文件有
#include<stdio.h> #include<stdlib.h> #include<malloc.h> #include<windows.h>
在這里我調用windows頭文件是為了在后面的代碼中修改控制臺的名稱,在實現線性表的鏈式存儲時真正用到的只有前三個頭文件
在寫各種函數之前先對一些表示結果狀態的字符進行預定義
//函數結果狀態代碼 #define TRUE 1 //代碼中出現TRUE相當于出現了1 #define FALSE 0 //出現FALSE相當于出現了0 #define OK 1 //出現OK相當于出現了1 #define ERROR 0 //出現ERROR相當于出現了0 #define INFEASIBLE -1 #define OVERFLOW -2 typedef int Status; //定義函數的返回狀態 typedef int ElemType;
在這里使用了typedef定義了Status和ElemType為int類型,也就是說之后的代碼當中如果出現了Status和ElemType,它們與int作用相同
typedef struct LNode{ ElemType data; //數據域 struct LNode * next; //指針域,指向一整個結點(結構體,該結構體中包含數據域和指針域) }LNode , * LinkList;
代碼中的* LinkList指的是結點的類型,在之后的代碼中出現了它就相當于出現了指向這個結點的指針
//構造一個空的頭結點 Status InitList_L(LinkList &L){ L = (LinkList)malloc(sizeof(LNode)); //產生頭結點,并使L指向該頭結點(L也稱頭指針) if(!L) return ERROR; //如果存儲空間分配失敗,返回ERROR L->next = NULL; //將指針域賦值為NULL printf("空的頭結點創建成功\n"); return OK; }
在該函數傳參時一定要在L之前加"&"符號,表示引用傳遞,保證形參和實參同時改變。之前在寫代碼時因為沒有輸入"&"符號,沒有使用引用傳遞也就意味著沒有開辟了新的內存空間,所以在之后賦值的時候會出現無法賦值的情況 在這里要強調一點:"->"是一個指針類型的運算符,它是用于指向結構體子數據的指針
//對線性表進行賦值 Status ValueList_L(LinkList &L,ElemType e){ LinkList s,p; p = L; while(p->next){ p = p->next; } s = (LinkList)malloc(sizeof(LNode)); //生成一個新結點 s->data = e; //將e賦值給新結點的數據域 s->next = p->next; //將新結點與后一個結點的地址連接 p->next = s; return OK; }
因為要實現構造一個單鏈表,所以在main函數中會循環調用ValueList_L方法,所以通過以下的循環是用來使p指向要賦值的位置
while(p->next){
p = p->next; }
之后利用malloc()函數開辟新的結點來存放數據和下一個結點的位置即可,因為malloc()函數開辟空間之后返回的不是LinkList結點類型,所以在利用malloc()函數開辟新的結點時要將其通過強制類型轉換使其轉換成LinkList類型
//對線性表進行銷毀 Status DistoryList_L(LinkList &L) { if(!L){ //如果線性表不存在,返回ERROR printf("線性表不存在\n"); return ERROR; } LinkList q = L->next; //使q指向單鏈表的首元結點 while(q != NULL){ //當q結點不為空時一直進入循環 free(L); //釋放L結點 L = q; //將q結點賦值給L結點 q = L->next; //將q結點賦值給L結點以后使q結點指向L的下一個結點 } free(L); //此時q的值為NULL,L指向尾結點,將其釋放 L = NULL; printf("線性表已銷毀\n"); }
在對單鏈表進行銷毀操作時,從頭結點開始逐一釋放,釋放前使q指向開始釋放的結點,當開始結點不為空時,執行釋放過程,先釋放頭結點,然后將L,q都向后移,依次釋放,因為q始終是L的后繼,所以最后一定是L留到最后,最后釋放L結點
L = NULL;
為什么在feel(L);之后還要將L賦值為空?
因為free函數只是將之前動態分配給L的內存歸還給系統,但是指針類型的結點L仍然存在,為了防止之后發生野指針訪問,將L賦值為NULL
//對線性表進行重置 Status ClearList_L(LinkList &L) { if(!L->next){ printf("線性表為空表,不需要重置\n"); return ERROR; } LinkList p,q; p = L->next; //將單鏈表的頭結點賦值給p while(p){ q = p->next; //將單鏈表的首元結點賦值給q free(p); p = q; } L->next = NULL; //將頭結點的指針域賦值為空 printf("線性表已重置\n"); return OK; }
在對線性表進行重置前首先要判斷線性表是為空表,當其不為空時構造兩個LinkList類型的結點p和q,使p指向L的首元結點,當p不為空即單鏈表不為空時進入while循環,將p的下一個結點復制給q,將p釋放后再將q賦值給p。p為空時說明此時單鏈表只剩下了頭結點,將頭結點的指針域設置為NULL,完成單鏈表的重置(因為LinkList為指針類型的數據,所以賦值的內容都是地址)
圖示:
//判斷線性表是否為空 Status ListEmpty_L(LinkList L) { if(L){ if(L->next == NULL) //如果首元結點不存在 printf("線性表是空表\n"); else printf("線性表不是空表\n"); } else{ printf("線性表不存在,無法判斷\n"); } return OK; }
在判斷線性表是否為空時,首先判斷頭結點是否存在,當頭結點存在時看頭結點的指針域是否為空,當指針域為空時說明首元結點不存在,單鏈表是空表;當指針域不為空時說明存在首元結點,單鏈表不是空表。如果頭結點不存在的話說明單鏈表不存在,無法判斷是否為空表。
//獲取線性表的長度 Status ListLength_L(LinkList L,int count) { //L為帶頭結點的單鏈表的頭指針,count為計數器 LinkList p = L->next; //定義p為單鏈表L的指針域 while(p){ p = p->next; count++; } return count; }
獲取線性表長度的核心思路是遍歷單鏈表,定義LinkList類型的變量p,將單鏈表的首元結點賦值給p。在該函數中count為計數器,形參count傳來的值始終為1,count的值為1代表從首元結點開始計數,所以才將L->next賦值給p,目的是為了讓count與存儲數據元素的結點位置對應一致。(在單鏈表中有頭結點的存在,所以這種方法計算出的長度最后的值要比線性表的實際長度大1)進入循環后每當p不斷向后移動,每當p后移一次,計數器count的值就加1,直到p為空,此時count的位置就對應著最后一個存儲著數據元素的結點位置。
//獲取線性表某一位置對應的元素 Status GetElem_L(LinkList L,int index) { LinkList p; p = L->next; //使p指向L的首元結點 int count = 1; //count為計數器 ,賦值等于1的原因是從首元結點開始計數 while(p && count < index){ //順著指針向后查找,直到p指向第index個元素或p為空 p = p->next; count++; //此時p一直指向第count個元素 } if(!p || count > index){ printf("當前位置沒有元素\n"); return ERROR; } printf("第%d個元素的值是:%d\n",index,p->data); return OK; }
與獲取單鏈表的長度思路一樣,獲取單鏈表某一位置的元素也需要遍歷單鏈表,只不過什么時候停止遍歷由自己決定,可能不需要全部遍歷。定義LinkList類型的變量p并且將首元結點的地址賦值給p。定義計數器count的初始值為1之后,進入while循環,循環判斷有兩個:
p 因為p一直指向第count個結點,所以此循環判斷條件的意思是當第count個結點存在時才能進入循環
count < index 當count還不是我們想要獲取的結點位置時繼續循環
退出循環以后p指向的位置就是我們想要獲取的結點位置,這個時候要先進行越界判斷,!p的意思是如果在之前的循環中index的值大于單鏈表的長度,那么退出循環的原因就是p為NULL,那么!p就為true,滿足if語句中的條件,返回ERROR,所以 !p的作用就是限制index不大于單鏈表的長度。 count > index的目的是為了限制index的值小于1
//在線性表某一位置插入元素 Status ListInsert_L(LinkList &L,int index,ElemType e) { LinkList p,q; p = L; //將線性表的頭結點賦值給p int count = 0; //count為計數器 while(p && count < index - 1){ //尋找第index-1個結點 p = p->next; //此時的p結點指向第index-1個結點 count++; } if(!p || count > index -1){ //越界判斷,index小于1或是index大于表長加1 printf("當前結點無法插入元素\n"); return ERROR; } q = (LinkList)malloc(sizeof(LNode)); q->data = e; //將e賦值到q的數據域當中 q->next = p->next; p->next = q; printf("元素插入成功\n"); return OK; }
與尋找某個位置結點的值思路一致,需要先找到要插入結點的位置。但是這里不同的地方在于要插入結點的話,可以在單鏈表的表尾插入元素,也可以在頭結點和首元結點間插入元素,所以計數器count的初值為0(為了保證從頭結點開始遍歷,count的值與實際的結點位置相匹配),所以判斷條件變為index - 1。在結束循環和越界判斷結束后p之后的位置就是要插入結點的位置,先構造出一個空結點并賦值給q,將p的下一個結點位置賦值給q的指針域,再將p的下一個結點位置賦值給q完成插入操作。
圖示:
//刪除線性表某一位置的元素 Status DeleteList_L(LinkList &L,int index) { LinkList p,q; p = L; //將線性表的頭結點賦值給p int count = 0; //計數器 while(p->next && count < index - 1){ p = p->next; count++; //此時p一直指向第count個結點 } if(!(p->next) || count > index - 1){ //越界判斷 printf("當前位置無法刪除元素\n"); return ERROR; } q = p->next; p->next = q->next; free(q); q = NULL; printf("當前位置元素已刪除\n"); return OK; }
刪除某一結點的思路仍然是從頭結點開始遍歷,找到要刪除的結點的位置的前一個結點,此時p就是要刪除結點位置的前一個結點。將p的后一個結點賦值給q,此時q就是要刪除的結點,將q的下一個結點與p的下一個結點連接,釋放q結點,完成刪除操作。
//求線性表某一元素的前驅 Status PriorElem_L(LinkList L,int index) { LinkList p; int count = 0; //count為計數器 p = L; while(p->next && count < index - 1){ //尋找第index-1個結點 p = p->next; //p一直指向第count個結點 count++; } if(!(p->next) || count > index - 1){ //越界判斷 printf("當前位置無法求該元素的前驅\n"); return ERROR; } if(p != L) //如果要獲取第一個元素的前驅,就是獲取頭結點數據域的值 printf("該元素的前驅為:%d\n",p->data); else printf("該位置的前驅是頭結點\n頭結點的數據域中存儲的值為:%d\n",p->data); return OK; }
和刪除結點的思路完全一致,只不過求前驅時不需要進行刪除結點,在循環中控制循環條件使p在index - 1位置結束循環,此時p指向的就是第index的前驅,直接將p結點的數據域輸出即可
//求線性表某一元素的后繼 Status NextElem_L(LinkList L,int index) { LinkList p; int count = 0; p = L->next; while(p && count < index){ //不斷遍歷尋找第index之后的結點 p = p->next; //p一直指向index-1的后一個結點 count++; } //!p的目的是為了確保i不大于表長-1,count>index的目的是為了確保index不小于0 if(!p || count > index){ //越界判斷 printf("當前位置無法求該元素的后繼\n"); return ERROR; } printf("該元素的后繼為:%d\n",p->data); }
在聲明LinkList類型變量p時將L的首元結點賦值給p,在循環中p一直指向第index的下一個結點,所以直接將p結點的數據域輸出即可
//打印線性表 Status PrintList_L(LinkList L) { if(!L){ //如果線性表不存在,返回ERROR printf("線性表不存在,無法打印\n"); return ERROR; } LinkList p; p = L->next; //將L的首元結點賦值給p ,為了不將頭結點打印出來 while(p){ printf(" %d",p->data); //將p結點的數據域輸出 p = p->next; //結點不斷的向后移動 } printf("\n"); return OK; }
打印單鏈表的思路也是進行對單鏈表的遍歷,在遍歷的過程中將每個結點的數據域中存儲的值輸出
為了方便演示,在這里為單鏈表一次賦值為1,2,3,4,5
構造一個空的頭結點
賦值操作
判斷此時線性表是否為空
獲取單鏈表的長度
獲取2號位置的元素
在3號位置插入520并打印單鏈表
獲取此時單鏈表的長度
刪除3號位置的元素并打印單鏈表
求3號位置元素的前驅和后繼
重置單鏈表并獲取長度以及判斷是否為空表
銷毀單鏈表并進行賦值和判斷是否為空
以上便是線性表鏈式表示和實現,由于鏈表在空間的合理利用上和插入、刪除是不需要移動等的優點,因此在很多場合下它
是線性表的首選存儲結構。然而,它也存在著實現某些基本操作的缺點,比如:求線性表長度時不如順序存儲結構......
#include<stdio.h> #include<stdlib.h> #include<malloc.h> #include<windows.h> //函數結果狀態代碼 #define TRUE 1 //代碼中出現TRUE相當于出現了1 #define FALSE 0 //出現FALSE相當于出現了0 #define OK 1 //出現OK相當于出現了1 #define ERROR 0 //出現ERROR相當于出現了0 #define INFEASIBLE -1 #define OVERFLOW -2 typedef int Status; //定義函數的返回狀態 typedef int ElemType; typedef struct LNode{ ElemType data; //數據域 struct LNode * next; //指針域,指向一整個結點(結構體,該結構體中包含數據域和指針域) }LNode , * LinkList; //* LinkList是結點的類型,在之后的代碼中出現了它就相當于出現了指向這個結點的指針 //構造一個空的頭結點 Status InitList_L(LinkList &L){ //之前因為沒有輸入"&"符號,沒有使用引用傳遞也就意味著沒有開辟了新的內存空間,所以在之后賦值的時候會出現無法賦值的情況 L = (LinkList)malloc(sizeof(LNode)); //產生頭結點,并使L指向該頭結點(L也稱頭指針) if(!L) return ERROR; //如果存儲空間分配失敗,返回ERROR L->next = NULL; //將指針域賦值為NULL,在這里要強調一點:"->"是一個整體,它是用于指向結構體子數據的指針 printf("空的頭結點創建成功\n"); return OK; } //對線性表進行賦值 Status ValueList_L(LinkList &L,ElemType e){ LinkList s,p; p = L; while(p->next){ p = p->next; } s = (LinkList)malloc(sizeof(LNode)); //生成一個新結點 s->data = e; //將e賦值給新結點的數據域 s->next = p->next; //將新結點與后一個結點的地址連接 p->next = s; return OK; } //對線性表進行銷毀 Status DistoryList_L(LinkList &L) { /*從頭結點開始逐一釋放,釋放前使p指向頭結點,q指向開始釋放的結點 當開始結點不為空時,執行釋放過程 先釋放頭結點,然后將p,q都向后移,依次釋放 因為q始終是p的后繼,所以最后一定是p留到最后,最后釋放p */ if(!L){ //如果線性表不存在,返回ERROR printf("線性表不存在\n"); return ERROR; } LinkList q = L->next; //使q指向單鏈表的首元結點 while(q != NULL){ //當q結點不為空時一直進入循環 free(L); //釋放L結點 L = q; //將q結點賦值給L結點 q = L->next; //將q結點賦值給L結點以后使q結點指向L的下一個結點 } free(L); //此時q的值為NULL,L指向尾結點,將其釋放 L = NULL; //free函數只是將之前動態分配給L的內存歸還給系統,但是指針類型的結點L仍然存在 //為了防止之后發生野指針訪問,將L賦值為NULL printf("線性表已銷毀\n"); } //對線性表進行重置 Status ClearList_L(LinkList &L) { if(!L->next){ printf("線性表為空表,不需要重置\n"); return ERROR; } LinkList p,q; p = L->next; //將單鏈表的頭結點賦值給p while(p){ q = p->next; //將單鏈表的首元結點賦值給q free(p); p = q; } L->next = NULL; //將頭結點的指針域賦值為空 printf("線性表已重置\n"); return OK; } //判斷線性表是否為空 Status ListEmpty_L(LinkList L) { if(L){ if(L->next == NULL) //如果首元結點不存在 printf("線性表是空表\n"); else printf("線性表不是空表\n"); } else{ printf("線性表不存在,無法判斷\n"); } return OK; } //獲取線性表的長度 Status ListLength_L(LinkList L,int count) { //L為帶頭結點的單鏈表的頭指針,count為計數器 LinkList p = L->next; //定義p為單鏈表L的指針域 while(p){ p = p->next; count++; } return count; } //獲取線性表某一位置對應的元素 Status GetElem_L(LinkList L,int index) { LinkList p; p = L->next; //使p指向L的首元結點 int count = 1; //count為計數器 ,賦值等于1的原因是從首元結點開始計數 while(p && count < index){ //順著指針向后查找,直到p指向第index個元素或p為空 p = p->next; count++; //此時p一直指向第count個元素 } if(!p || count > index){ printf("當前位置沒有元素\n"); return ERROR; } printf("第%d個元素的值是:%d\n",index,p->data); return OK; } //在線性表某一位置插入元素 Status ListInsert_L(LinkList &L,int index,ElemType e) { LinkList p,q; p = L; //將線性表的頭結點賦值給p int count = 0; //count為計數器 while(p && count < index - 1){ //尋找第index-1個結點 p = p->next; //此時的p結點指向第index-1個結點 count++; } if(!p || count > index -1){ //越界判斷,index小于1或是index大于表長加1 printf("當前結點無法插入元素\n"); return ERROR; } q = (LinkList)malloc(sizeof(LNode)); q->data = e; //將e賦值到q的數據域當中 q->next = p->next; p->next = q; printf("元素插入成功\n"); return OK; } //刪除線性表某一位置的元素 Status DeleteList_L(LinkList &L,int index) { LinkList p,q; p = L; //將線性表的頭結點賦值給p int count = 0; //計數器 while(p->next && count < index - 1){ p = p->next; count++; //此時p一直指向第count個結點 } if(!(p->next) || count > index - 1){ //越界判斷 printf("當前位置無法刪除元素\n"); return ERROR; } q = p->next; p->next = q->next; free(q); q = NULL; printf("當前位置元素已刪除\n"); return OK; } //求線性表某一元素的前驅 Status PriorElem_L(LinkList L,int index) { LinkList p; int count = 0; //count為計數器 p = L; while(p->next && count < index - 1){ //尋找第index-1個結點 p = p->next; //p一直指向第count個結點 count++; } if(!(p->next) || count > index - 1){ //越界判斷 printf("當前位置無法求該元素的前驅\n"); return ERROR; } if(p != L) //如果要獲取第一個元素的前驅,就是獲取頭結點數據域的值 printf("該元素的前驅為:%d\n",p->data); else printf("該位置的前驅是頭結點\n頭結點的數據域中存儲的值為:%d\n",p->data); return OK; } //求線性表某一元素的后繼 Status NextElem_L(LinkList L,int index) { LinkList p; int count = 0; p = L->next; while(p && count < index){ //不斷遍歷尋找第index之后的結點 p = p->next; //p一直指向index-1的后一個結點 count++; } //!p的目的是為了確保i不大于表長-1,count>index的目的是為了確保index不小于0 if(!p || count > index){ //越界判斷 printf("當前位置無法求該元素的后繼\n"); return ERROR; } printf("該元素的后繼為:%d\n",p->data); } //打印線性表 Status PrintList_L(LinkList L) { if(!L){ //如果線性表不存在,返回ERROR printf("線性表不存在,無法打印\n"); return ERROR; } LinkList p; p = L->next; //將L的首元結點賦值給p ,為了不將頭結點打印出來 while(p){ printf(" %d",p->data); //將p結點的數據域輸出 p = p->next; //結點不斷的向后移動 } printf("\n"); return OK; } int main(){ SetConsoleTitle("Dream_飛翔"); //控制windows終端控制臺的名稱 //system("mode con cols=60 lines=30"); 這條語句可以控制windows終端控制臺的大小 LinkList L = NULL; //聲明線性表的頭結點,但是并未進行初始化 int choose,index,e,Num,Value,k; while(1){ printf("*****************************************\n"); printf("* *\n"); printf("* 線性表的鏈式表示和實現: *\n"); printf("* *\n"); printf("* 1. 構造一個空的頭結點 *\n"); printf("* 2. 對線性表進行賦值 *\n"); printf("* 3. 對線性表進行銷毀 *\n"); printf("* 4. 對線性表進行重置 *\n"); printf("* 5. 判斷線性表是否為空 *\n"); printf("* 6. 獲取線性表的長度 *\n"); printf("* 7. 獲取線性表某一位置對應的元素 *\n"); printf("* 8. 在線性表某一位置插入元素 *\n"); printf("* 9. 刪除線性表某一位置的元素 *\n"); printf("* 10. 求線性表某一元素的前驅 *\n"); printf("* 11. 求線性表某一元素的后繼 *\n"); printf("* 12. 打印線性表 *\n"); printf("* 13. 退出 *\n"); printf("* *\n"); printf("*****************************************\n"); printf("請做出您的選擇:"); scanf("%d",&choose); switch(choose){ case 1:InitList_L(L);break; case 2:{ if(L){ //對線性表賦值的前提是線性表的頭結點存在 printf("請輸入線性表元素的個數:"); scanf("%d",&Num); if(Num > 0){ for(int i = 1;i <= Num;i++){ printf("請輸入第%d個元素的值:",i); scanf("%d",&Value); ValueList_L(L,Value); } printf("線性表賦值成功\n"); } else printf("請輸入一個有效數字\n"); } else printf("線性表不存在,無法賦值\n"); } break; case 3:DistoryList_L(L);break; case 4:ClearList_L(L);break; case 5:ListEmpty_L(L);break; case 6:{ int count = ListLength_L(L,1); printf("線性表的長度為:%d\n",count-1); };break; case 7:{ printf("請輸入要獲取元素的位置:"); scanf("%d",&index); GetElem_L(L,index); } break; case 8:{ printf("請輸入插入元素的位置:"); scanf("%d",&index); printf("請輸入插入元素的值:"); scanf("%d",&e); ListInsert_L(L,index,e); } break; case 9:{ printf("請輸入要刪除元素的位置:"); scanf("%d",&index); DeleteList_L(L,index); } break; case 10:{ if(L){ printf("請輸入想要查找哪一個元素的前驅:"); scanf("%d",&index); PriorElem_L(L,index); } else printf("線性表不存在,無法獲取其中元素的前驅\n"); } break; case 11:{ if(L){ printf("請輸入想要查找哪一個元素的后繼:"); scanf("%d",&index); NextElem_L(L,index); } else printf("線性表不存在,無法獲取其中元素的后繼\n"); } break; case 12:PrintList_L(L);break; case 13:exit(0); } } return 0; }
以上就是“C語言線性表鏈式表示及實現的方法”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。