首頁 > 軟體

C語言線性表的鏈式表示及實現詳解

2022-07-04 18:05:52

前言

線性表的順序表示指的是用一組地址連續的儲存單元依次儲存線性表的資料元素,而線性表的鏈式儲存特點則是用一組任意的儲存單元儲存線性表的資料元素。這組儲存單元既可以是連續的,也可以是不連續的。

對於鏈式儲存的每個資料元素而言,除了儲存其本身的資訊之外,還需要儲存一個指示其直接後繼的資訊,即直接後繼的儲存位置。這兩部分資訊組成了資料元素的儲存映像,稱為結點

鏈式儲存的結構包含兩個域:一個用於儲存資料元素的資訊,另一個用於儲存直接後繼的儲存位置;儲存資料元素資訊的域稱為資料域儲存直接後繼儲存位置的域稱為指標域

圖示:

資料結構中,在單連結串列的開始結點之前一般要附設一個型別相同的結點,稱之為頭結點頭結點的資料域可以不儲存任何資訊,頭結點的指標域儲存指向開始結點的指標,即第一個元素結點的儲存位置。

附設頭結點的作用:

  • 防止單連結串列是空的而設的。當連結串列為空的時候,帶頭結點的頭指標就指向頭結點,如果當連結串列為空的時候,單連結串列沒有帶頭結點,那麼它的頭指標就為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作用相同

1. 單連結串列的結點構造

typedef struct LNode{
	ElemType  data;               //資料域 
	struct LNode * next;          //指標域,指向一整個結點(結構體,該結構體中包含資料域和指標域) 
}LNode , * LinkList;        

程式碼中的* LinkList指的是結點的型別,在之後的程式碼中出現了它就相當於出現了指向這個結點的指標

2. 構造一個空的頭結點

//構造一個空的頭結點
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之前加"&"符號,表示參照傳遞,保證形參和實參同時改變。之前在寫程式碼時因為沒有輸入"&"符號,沒有使用參照傳遞也就意味著沒有開闢了新的記憶體空間,所以在之後賦值的時候會出現無法賦值的情況 在這裡要強調一點:"->"是一個指標型別的運運算元,它是用於指向結構體子資料的指標

3. 對線性表進行賦值

//對線性表進行賦值 
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型別

4.對線性表進行銷燬

//對線性表進行銷燬
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

5.對線性表進行重置

//對線性表進行重置
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為指標型別的資料,所以賦值的內容都是地址

圖示:

6.判斷線性表是否為空

//判斷線性表是否為空
Status ListEmpty_L(LinkList L)
{
	if(L){
		if(L->next == NULL)       //如果首元結點不存在 
	    printf("線性表是空表n");
	    else
	    printf("線性表不是空表n");
	}
	else{
	printf("線性表不存在,無法判斷n");	
	}
	return OK;
}

在判斷線性表是否為空時,首先判斷頭結點是否存在,當頭結點存在時看頭結點的指標域是否為空,當指標域為空時說明首元結點不存在,單連結串列是空表當指標域不為空時說明存在首元結點,單連結串列不是空表。如果頭結點不存在的話說明單連結串列不存在,無法判斷是否為空表。

7.獲取線性表的長度

//獲取線性表的長度
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的位置就對應著最後一個儲存著資料元素的結點位置。

8.獲取線性表某一位置對應的元素

//獲取線性表某一位置對應的元素
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個元素的值是:%dn",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

9.線上性表某一位置插入元素

//線上性表某一位置插入元素
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完成插入操作。

圖示:

10.刪除線性表某一位置的元素

//刪除線性表某一位置的元素
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結點,完成刪除操作。

11.求線性表某一元素的前驅

//求線性表某一元素的前驅 
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("該元素的前驅為:%dn",p->data);
	else
	printf("該位置的前驅是頭結點n頭結點的資料域中儲存的值為:%dn",p->data);
	return OK;
}

和刪除結點的思路完全一致,只不過求前驅時不需要進行刪除結點,在迴圈中控制迴圈條件使p在index - 1位置結束迴圈,此時p指向的就是第index的前驅,直接將p結點的資料域輸出即可

12.求線性表某一元素的後繼

//求線性表某一元素的後繼 
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("該元素的後繼為:%dn",p->data);
}

在宣告LinkList型別變數p時將L的首元結點賦值給p,在迴圈中p一直指向第index的下一個結點,所以直接將p結點的資料域輸出即可

13.列印線性表

//列印線性表
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個元素的值是:%dn",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("該元素的前驅為:%dn",p->data);
	else
	printf("該位置的前驅是頭結點n頭結點的資料域中儲存的值為:%dn",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("該元素的後繼為:%dn",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("線性表的長度為:%dn",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語言線性表的鏈式表示及實現詳解的詳細內容,更多關於C語言線性錶鏈式表示的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com