1. 程式人生 > >資料結構之線性表的鏈式儲存實現(附完整程式碼)

資料結構之線性表的鏈式儲存實現(附完整程式碼)

順序表插入、刪除時需要通過移動資料來實現,影響了執行效率。

而連結串列不要求邏輯上相鄰的兩個資料元素物理上也相鄰,因此對線性表的插入、刪除不需要移動資料元素,只需要修改鏈。

下面介紹帶頭結點的鏈式表:

資料結構:

typedef int ElementType;
typedef struct LNode * PtrToLNode;
struct LNode{
	ElementType Data;
	PtrToLNode Next;
};
typedef PtrToLNode Position;//這裡的位置是結點的地址 
typedef PtrToLNode List; 

1.初始化:

//初始化
List MakeEmpty(){
	List L;
	L = (List)malloc(sizeof (struct LNode));
	if (!L)
		exit (-1);
	L->Next = NULL;
	return L;
} 

2.求表長

在順序儲存表示的線性表中求表長是一件很容易的事,直接返回Last+1值就可以了,但是在鏈式儲存表示中,需要將連結串列從頭到尾遍歷一遍;設一個移動的指標p和計數器cnt,初始化後,p從表的第一個結點開始往後移,同時計數器cnt+1.


//求表長
int Length(List L){
	Position p;
	int cnt = 0;
	p = L->Next;
	while(p){
		p = p -> Next;
		cnt++;
	}
	return cnt;
} 

3.查詢(按序號查詢FindKth)

對於順序儲存,按序號查詢是很直接的事,要得到第k個元素的值,直接取L->Data[k-1]就可以了。而對於鏈式表就需要採用求表長的思路,從頭遍歷,判斷當前結點是否是第K個,若是,返回該結點的值,否則繼續後一個。

//根據指定的位序查詢s
int FindKth(List L,int K){
	Position p;
	int cnt = 1;//位序從1開始 
	p = L->Next; 
	while(p&&cnt<K){
		p = p-> Next;
		cnt++;
	}
	if((cnt==K)&&p) printf("您查詢的數為:%d\n",p -> Data);
	else printf("您查詢數不存在");
}

4.查詢(按值查詢Find)

按值查詢的方法也是從頭到尾遍歷,直到找到為止

//按值查詢 
Position Find(List L,int X){
	Position p;
	p = L->Next; 
	while(p&&p->Data!=X){
		p = p-> Next;
	}
	if(p) printf("查詢成功,您查詢的數為:%d\n",p->Data);
	else printf("您查詢數不存在");
}

5.插入

帶頭結點的鏈式表的插入

//插入
List Insert(List L ,ElementType X,int i){
	Position tmp,pre;
	int cnt =0 ;
	pre = L;
	while(pre&&cnt<i-1){
		pre = pre->Next;
		cnt++;
	}
	if(pre==NULL||cnt!=i-1){
		printf("插入位置引數錯誤\n");
	}
	else{
		tmp = (Position)malloc(sizeof(struct LNode));
		tmp->Data=X;
		tmp->Next=pre->Next;
		pre->Next=tmp;
	}
	
} 

6.刪除

刪除指定位序i的元素,首先需要找到被刪除結點的前一個元素,然後再刪除結點並釋放空間。

//刪除
bool Delete(List L,int i){
	Position tmp,pre;
	int cnt = 0;
	pre = L;
	while(pre&&cnt<i-1){
		pre=pre->Next;
		cnt++;
	}
	if(pre==NULL||cnt!=i-1||pre->Next==NULL){
		printf("刪除位置引數錯誤");
	}
	else{
		tmp = pre->Next;
		pre->Next = tmp->Next;
		free(tmp);
		printf("刪除成功"); 
	}
} 

7.遍歷連結串列並輸出

void DisLinkList(List L)
{
	List p = L->Next;
	printf("輸出連結串列: "); 
	while (p)
	{
		printf("%d ", p->Data);
		p = p->Next;
	}
}

完整的程式程式碼:

#include<stdio.h>
#include<stdlib.h>
typedef int ElementType;
typedef struct LNode * PtrToLNode;
struct LNode{
	ElementType Data;
	PtrToLNode Next;
};
typedef PtrToLNode Position;//這裡的位置是結點的地址 
typedef PtrToLNode List; 
//初始化
List MakeEmpty(){
	List L;
	L = (List)malloc(sizeof (struct LNode));
	if (!L)
		exit (-1);
	L->Next = NULL;
	return L;
} 

//根據指定的位序查詢
int FindKth(List L,int K){
	Position p;
	int cnt = 1;//位序從1開始 
	p = L->Next; 
	while(p&&cnt<K){
		p = p-> Next;
		cnt++;
	}
	if((cnt==K)&&p) printf("您查詢的數為:%d\n",p -> Data);
	else printf("您查詢數不存在");
}

//按值查詢 
Position Find(List L,int X){
	Position p;
	p = L->Next; 
	while(p&&p->Data!=X){
		p = p-> Next;
	}
	if(p) printf("查詢成功,您查詢的數為:%d\n",p->Data);
	else printf("您查詢數不存在");
}

//插入
List Insert(List L ,ElementType X,int i){
	Position tmp,pre;
	int cnt =0 ;
	pre = L;
	while(pre&&cnt<i-1){
		pre = pre->Next;
		cnt++;
	}
	if(pre==NULL||cnt!=i-1){
		printf("插入位置引數錯誤\n");
	}
	else{
		tmp = (Position)malloc(sizeof(struct LNode));
		tmp->Data=X;
		tmp->Next=pre->Next;
		pre->Next=tmp;
	}
	
} 

//刪除
bool Delete(List L,int i){
	Position tmp,pre;
	int cnt = 0;
	pre = L;
	while(pre&&cnt<i-1){
		pre=pre->Next;
		cnt++;
	}
	if(pre==NULL||cnt!=i-1||pre->Next==NULL){
		printf("刪除位置引數錯誤");
	}
	else{
		tmp = pre->Next;
		pre->Next = tmp->Next;
		free(tmp);
		printf("刪除成功"); 
	}
} 

//求表長
int Length(List L){
	Position p;
	int cnt = 0;
	p = L->Next;
	while(p){
		p = p -> Next;
		cnt++;
	}
	return cnt;
} 

void DisLinkList(List L)
{
	List p = L->Next;
	printf("輸出連結串列: "); 
	while (p)
	{
		printf("%d ", p->Data);
		p = p->Next;
	}
}

int main(){
	Position pre;
	Position L = MakeEmpty();
	pre = L;
	int i,n,x,len,cz,del;
	//插入 
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%d",&x);
		Insert(pre,x,i);
	}
	//輸出 
	DisLinkList(pre);
	printf("\n");
	//求表長 
	len = Length(L);
	printf("表長為:%d",len);
	printf("\n");
	//按值查詢
	printf("請輸入你要按值查詢的數:\n");
	scanf("%d",&cz);
	Find(L,cz);
	printf("\n");
	//按序號查詢
	printf("請輸入你要按序號查詢的數的序號:\n");
	scanf("%d",&cz);
	FindKth(L,cz);
	printf("\n");
	//刪除
	printf("請輸入你要刪除的數的下標:\n",del);
	scanf("%d",&del);
	Delete(L,del);
	DisLinkList(pre);
	printf("\n");
	return 0;
}

執行結果: