(一)數據結構之線性表的簡單實現:鏈表

1、線性表的定義

線性表(Linear List):由同類型的數據元素構成的有序序列的線性結構:表中元素個數稱爲線性表的長度,線性表沒有元素時,稱爲空表,表起始位置稱表頭,表結束位置稱爲表尾。

2、鏈表的順序存儲的實現

2.1 數據結構表示

利用數組的連續存儲空間順序存放線性表的各元素。首先定義鏈表的基本數據結構如下所示:

/* 定義List的基本結構 */	
#define MAXSIZE 	10			// 鏈表的長度
typedef int ElementType;
typedef struct _List{
	ElementType Data[MAXSIZE];		
	int Last;	// 鏈表中最後一個元素的下標
} List;

2.2 創建一個空鏈表

/* 初始化一個鏈表,即構造一個空表 */
List *MakeEmpty( )
{ 
	List *PtrL;
	PtrL = (List *)malloc( sizeof(List) );
	PtrL->Last = -1;
	return PtrL;
}

2.3 插入操作

/*	插入操作:在第i個位置上插入一個元素X	*/
void Insert( ElementType X, int i, List *PtrL )
{ 
	int j = 0;
	if ( PtrL->Last == MAXSIZE-1 )
	{ 
		/* 表空間已滿,不能插入*/
		printf("Table is full!\n");
		return;
	}
	if ( i < 1 || i > PtrL->Last+2) 
	{ 
		/*檢查插入位置的合法性*/
		printf("The position of insert is illegal!\n");
		return;
	}
	for ( j = PtrL->Last; j >= i-1; j-- )
		PtrL->Data[j+1] = PtrL->Data[j]; 	/*將 ai~an倒序向後移動*/
	PtrL->Data[i-1] = X; 					/*新元素插入*/
	PtrL->Last++; 							/*Last仍指向最後元素*/
	return;
}

2.4 刪除操作

/* 刪除表第i個元素 */
void Delete( int i, List *PtrL )
{ 
	int j = 0;
	if( i < 1 || i > PtrL->Last+1 ) 
	{ 
		/*檢查空表及刪除位置的合法性*/
		printf ("The position of delete is illegal!\n");
		return ;
	}
	for ( j = i; j <= PtrL->Last; j++ )
		PtrL->Data[j-1] = PtrL->Data[j]; 	/*將 ai+1~ an順序向前移動*/
	PtrL->Last--; 							/*Last仍指向最後元素*/
	return;
}

2.5 查找操作

/**	查找:按指定元素來查找
  *		X 要查找的元素值
  *		PtrL 要查找的鏈表的頭結點指針
  *		返回值 對應元素的下標
  */
int Find( ElementType X, List *PtrL )
{ 
	int i = 0;
	while( i <= PtrL->Last && PtrL->Data[i]!= X )
		i++;
	if (i > PtrL->Last) return -1; /* 如果沒找到,返回-1 */
	else return i; /* 找到後返回的是存儲位置 */
}

2.6 修改操作

/* 修改元素值 */
void Change( ElementType X, int i, List *PtrL)
{
	if ( i < 1 || i > PtrL->Last+1) 
	{ 
		/*檢查插入位置的合法性*/
		printf("The position of change is illegal!\n");
		return;
	}
	PtrL->Data[i - 1] = X;	/* 對要修改的元素進行賦值 */
}

2.7 完整的示例代碼

/**	線性表的順序存儲
  *		Date : 2017-09-10
  */
#include <stdio.h>
#include <stdlib.h>

/* 定義List的基本結構 */	
#define MAXSIZE 	10			// 鏈表的長度
typedef int ElementType;
typedef struct _List{
	ElementType Data[MAXSIZE];		
	int Last;	// 鏈表中最後一個元素的下標
} List;

/* 初始化一個鏈表,即構造一個空表 */
List *MakeEmpty( )
{ 
	List *PtrL;
	PtrL = (List *)malloc( sizeof(List) );
	PtrL->Last = -1;
	return PtrL;
}

/* 銷燬一個鏈表,釋放內存空間 */
void MakeDestroy(List *PtrL)
{
	if(PtrL != NULL) free(PtrL);
	PtrL = NULL;
}

/**	查找:按指定元素來查找
  *		X 要查找的元素值
  *		PtrL 要查找的鏈表的頭結點指針
  *		返回值 對應元素的下標
  */
int Find( ElementType X, List *PtrL )
{ 
	int i = 0;
	while( i <= PtrL->Last && PtrL->Data[i]!= X )
		i++;
	if (i > PtrL->Last) return -1; /* 如果沒找到,返回-1 */
	else return i; /* 找到後返回的是存儲位置 */
}

/*	插入操作:在第i個位置上插入一個元素X	*/
void Insert( ElementType X, int i, List *PtrL )
{ 
	int j = 0;
	if ( PtrL->Last == MAXSIZE-1 )
	{ 
		/* 表空間已滿,不能插入*/
		printf("Table is full!\n");
		return;
	}
	if ( i < 1 || i > PtrL->Last+2) 
	{ 
		/*檢查插入位置的合法性*/
		printf("The position of insert is illegal!\n");
		return;
	}
	for ( j = PtrL->Last; j >= i-1; j-- )
		PtrL->Data[j+1] = PtrL->Data[j]; 	/*將 ai~an倒序向後移動*/
	PtrL->Data[i-1] = X; 					/*新元素插入*/
	PtrL->Last++; 							/*Last仍指向最後元素*/
	return;
}

/* 刪除表第i個元素 */
void Delete( int i, List *PtrL )
{ 
	int j = 0;
	if( i < 1 || i > PtrL->Last+1 ) 
	{ 
		/*檢查空表及刪除位置的合法性*/
		printf ("The position of delete is illegal!\n");
		return ;
	}
	for ( j = i; j <= PtrL->Last; j++ )
		PtrL->Data[j-1] = PtrL->Data[j]; 	/*將 ai+1~ an順序向前移動*/
	PtrL->Last--; 							/*Last仍指向最後元素*/
	return;
}

/* 修改元素值 */
void Change( ElementType X, int i, List *PtrL)
{
	if ( i < 1 || i > PtrL->Last+1) 
	{ 
		/*檢查插入位置的合法性*/
		printf("The position of change is illegal!\n");
		return;
	}
	PtrL->Data[i - 1] = X;	/* 對要修改的元素進行賦值 */
}

/* 遍歷這個鏈表中的元素 */
void Traversal(List *PtrL)
{
	int i = 0;
	if((PtrL == NULL) || (PtrL->Last < 0))
	{
		printf("List is illegal!\n");
		return ;
	}
	for(i = 0; i <= PtrL->Last; i++)
		printf("%d ", PtrL->Data[i]);
	printf("\n");
}

/* 返回線性表的長度 */
int Length(List *PtrL)
{
	if(PtrL == NULL)
	{
		printf("List is illegal!\n");
		return -1;
	}
	return PtrL->Last + 1;
}

/* 程序入口 */
int main()
{
	int i, index;
	ElementType temp;
	List *list;

	list = MakeEmpty();	/* 創建一個鏈表 */

	/* 向鏈表中插入五個元素 */
	printf("Input 5 numbers : ");
	for(i = 0; i < 5; i++)
	{
		scanf("%d", &temp);
		Insert(temp, i+1, list);		// 注意這裏要插入的是第i個元素,而數組的下標是從零開始的,所以要加一
	}

	printf("************************************Traversal*****************************\n");
	/* 打印鏈表中的元素 */
	Traversal(list);
	printf("Length = %d\n", Length(list));

	printf("************************************Delete********************************\n");
	/* 刪除一個元素 */
	Delete(3, list);
	Traversal(list);	
	printf("Length = %d\n", Length(list));

	printf("************************************Insert********************************\n");
	/* 插入一個元素 */
	Insert(100, 2, list);
	Traversal(list);	
	printf("Length = %d\n", Length(list));

	printf("************************************Change********************************\n");
	/* 插入一個元素 */
	Change(888, 1, list);
	Traversal(list);	
	printf("Length = %d\n", Length(list));

	printf("************************************Find*********************************\n");
	/* 查找一個元素 */
	index = Find(100, list);
	Traversal(list);	
	printf("Length = %d, Index = %d\n", Length(list), index);

	MakeDestroy(list);		/* 銷燬這個鏈表 */
	
	return 0;
}

3、鏈表的鏈式存儲的實現

不要求邏輯上相鄰的兩個元素物理上也相鄰;通過鏈建立起數據元素之間的邏輯關係;插入、刪除不需要移動數據元素,只需要修改鏈。

3.1 基本數據結構

/* 基本數據結構定義 */
typedef int ElementType;
typedef struct Node{
	ElementType Data;
	struct Node *Next;
} List;

3.2 插入操作

通過插入操作就可以創建一個鏈式鏈表,所以不需要單獨爲其創建一個頭結點。
/* 在第i個結點位置上插入一個新結點 */
List *Insert( ElementType X, int i, List *PtrL )
{ 
	List *p, *s;
	if ( i == 1 ) 
	{ 
		/* 新結點插入在表頭 */
		s = (List *)malloc(sizeof(List)); /*申請、填裝結點*/
		s->Data = X;
		s->Next = PtrL;
		return s; /*返回新表頭指針*/
	}
	p = FindKth( i-1, PtrL ); /* 查找第i-1個結點 */
	if ( p == NULL ) 
	{ 
		/* 第i-1個不存在,不能插入 */
		printf("the node of i-1 is not exist!\n");
		return NULL;
	}
	else 
	{
		s = (List *)malloc(sizeof(List)); /*申請、填裝結點*/
		s->Data = X;
		s->Next = p->Next; /*新結點插入在第i-1個結點的後面*/
		p->Next = s;
		return PtrL;
	}
}

3.3 刪除操作

/* 刪除第i個結點 */
List *Delete( int i, List *PtrL )
{ 
	List *p, *s;
	if ( i == 1 ) 
	{ 
		/* 若要刪除的是表的第一個結點 */
		s = PtrL; 								/*s指向第1個結點*/
		if (PtrL!=NULL) PtrL = PtrL->Next; 		/*從鏈表中刪除*/
		else return NULL;
		free(s); 								/*釋放被刪除結點 */
		return PtrL;
	}
	p = FindKth( i-1, PtrL ); /*查找第i-1個結點*/
	if ( p == NULL ) 
	{
		printf("the node of i-1 is not exist!\n"); return NULL;
	} 
	else if ( p->Next == NULL )
	{
		printf("the node of i is not exist!\n"); return NULL;
	} 
	else 
	{
		s = p->Next; 		/*s指向第i個結點*/
		p->Next = s->Next; 	/*從鏈表中刪除*/
		free(s); 			/*釋放被刪除結點 */
		return PtrL;
	}
}

3.4 查找操作

查找操作實現了兩種:一種是按照元素值查找,還有一種是按照存在鏈表中的位置來查找具體實現如下:
按元素值來查找:
/* 查找鏈表中值爲X的元素 */
List *Find( ElementType X, List *PtrL )
{
	List *p = PtrL;
	while ( p!=NULL && p->Data != X )
		p = p->Next;
	return p;
}
按位置來查找:
/* 查找鏈表中第K個元素 */
List *FindKth( int K, List *PtrL )
{ 
	List *p = PtrL;
	int i = 1;
	while (p != NULL && i < K )
	{
		p = p->Next;
		i++;
	}
	if ( i == K ) return p;	/* 找到第K個,返回指針 */
	else return NULL;		/* 否則返回空 */
}

3.5 修改操作

/* 修改元素值 */
void Change( ElementType X, int i, List *PtrL)
{
	List *p;
	p = FindKth( i, PtrL ); /* 查找第i個結點 */
	if ( p == NULL ) 
	{ 
		/* 第i-1個不存在,不能插入 */
		printf("the node of i-1 is not exist!\n");
		return ;
	}
	else
	{
		p->Data = X;
	}
}

3.6 完整的示例代碼實現

/* 線性表的鏈式存儲 */
#include <stdio.h>
#include <stdlib.h>

/* 基本數據結構定義 */
typedef int ElementType;
typedef struct Node{
	ElementType Data;
	struct Node *Next;
} List;

/* 銷燬一個鏈表,釋放內存空間 */
void MakeDestroy(List *PtrL)
{
	List *PtrTemp = PtrL;
	List *PtrNext;
	while(PtrTemp)
	{
		PtrNext = PtrTemp->Next;
		free(PtrTemp);
		PtrTemp = PtrNext;
	}
}

/* 查找鏈表中第K個元素 */
List *FindKth( int K, List *PtrL )
{ 
	List *p = PtrL;
	int i = 1;
	while (p != NULL && i < K )
	{
		p = p->Next;
		i++;
	}
	if ( i == K ) return p;	/* 找到第K個,返回指針 */
	else return NULL;		/* 否則返回空 */
}

/* 查找鏈表中值爲X的元素 */
List *Find( ElementType X, List *PtrL )
{
	List *p = PtrL;
	while ( p!=NULL && p->Data != X )
		p = p->Next;
	return p;
}

/* 在第i個結點位置上插入一個新結點 */
List *Insert( ElementType X, int i, List *PtrL )
{ 
	List *p, *s;
	if ( i == 1 ) 
	{ 
		/* 新結點插入在表頭 */
		s = (List *)malloc(sizeof(List)); /*申請、填裝結點*/
		s->Data = X;
		s->Next = PtrL;
		return s; /*返回新表頭指針*/
	}
	p = FindKth( i-1, PtrL ); /* 查找第i-1個結點 */
	if ( p == NULL ) 
	{ 
		/* 第i-1個不存在,不能插入 */
		printf("the node of i-1 is not exist!\n");
		return NULL;
	}
	else 
	{
		s = (List *)malloc(sizeof(List)); /*申請、填裝結點*/
		s->Data = X;
		s->Next = p->Next; /*新結點插入在第i-1個結點的後面*/
		p->Next = s;
		return PtrL;
	}
}

/* 刪除第i個結點 */
List *Delete( int i, List *PtrL )
{ 
	List *p, *s;
	if ( i == 1 ) 
	{ 
		/* 若要刪除的是表的第一個結點 */
		s = PtrL; 								/*s指向第1個結點*/
		if (PtrL!=NULL) PtrL = PtrL->Next; 		/*從鏈表中刪除*/
		else return NULL;
		free(s); 								/*釋放被刪除結點 */
		return PtrL;
	}
	p = FindKth( i-1, PtrL ); /*查找第i-1個結點*/
	if ( p == NULL ) 
	{
		printf("the node of i-1 is not exist!\n"); return NULL;
	} 
	else if ( p->Next == NULL )
	{
		printf("the node of i is not exist!\n"); return NULL;
	} 
	else 
	{
		s = p->Next; 		/*s指向第i個結點*/
		p->Next = s->Next; 	/*從鏈表中刪除*/
		free(s); 			/*釋放被刪除結點 */
		return PtrL;
	}
}

/* 修改元素值 */
void Change( ElementType X, int i, List *PtrL)
{
	List *p;
	p = FindKth( i, PtrL ); /* 查找第i個結點 */
	if ( p == NULL ) 
	{ 
		/* 第i-1個不存在,不能插入 */
		printf("the node of i-1 is not exist!\n");
		return ;
	}
	else
	{
		p->Data = X;
	}
}

/* 遍歷這個鏈表中的元素 */
void Traversal(List *PtrL)
{
	List *p;
	p = PtrL;
	while(p)
	{
		printf("%d ", p->Data);
		p = p->Next;
	}
}


/* 求表長 */
int Length ( List *PtrL )
{ 
	List *p = PtrL; /* p指向表的第一個結點*/
	int j = 0;
	while ( p ) 
	{
		p = p->Next;
		j++; 		/* 當前p指向的是第 j 個結點*/
	}
	return j;
}


/* 程序入口 */
int main()
{
	int i, index;
	ElementType temp;
	List *node;
	List *list = NULL;		/* 防止野指針 */
	
	/* 向鏈表中插入五個元素 */
	printf("Input 5 numbers : ");
	for(i = 0; i < 5; i++)
	{
		scanf("%d", &temp);
		list = Insert(temp, i + 1, list);
	}

	printf("************************************Traversal*****************************\n");
	/* 打印鏈表中的元素 */
	Traversal(list);
	printf("Length = %d\n", Length(list));

	printf("************************************Delete********************************\n");
	/* 刪除一個元素 */
	list = Delete(3, list);
	Traversal(list);	
	printf("Length = %d\n", Length(list));

	printf("************************************Insert********************************\n");
	/* 插入一個元素 */
	Insert(100, 2, list);
	Traversal(list);	
	printf("Length = %d\n", Length(list));

	printf("************************************Change********************************\n");
	/* 插入一個元素 */
	Change(888, 1, list);
	Traversal(list);	
	printf("Length = %d\n", Length(list));

	printf("************************************Find**********************************\n");
	/* 查找一個元素 */
	node = Find(100, list);
	Traversal(list);	
	printf("Length = %d, Value = %d\n", Length(list), node->Data);

	MakeDestroy(list);		/* 銷燬這個鏈表 */
	
	return 0;	
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章