順序表、單鏈表——C語言實現及其比較

(一)順序表的實現

順序表的存儲結構定義

#define MaxSize 100
typedef int DataType;
typedef struct
{
	DataType data[MaxSize];	//存儲數組 
	int length;	//順序表的長度 
} seqList;

順序表的實現

函數聲明

/* 函數聲明 */ 
//	1)、初始化順序表
void initList(seqList *L);
//	2)、創建順序表
int creatList(seqList *L, DataType arr[], int n);
//	3)、銷燬順序表 :順序表是靜態存儲分配,在順序表變量退出做用域時自動釋放所佔內存單元 
//	4)、判空操做
int isEmpty(seqList *L);
//	5)、求順序表的長度
int getLength(seqList *L);
//	6)、遍歷操做
int printList(seqList *L);
//	7)、按值查找
int locate(seqList *L, DataType n);
//	8)、按位查找
	/*
		L:順序表指針
		i:須要查找第幾個元素 
		ptr:存儲查找到的元素 
	*/
int get(seqList *L, DataType i, DataType *ptr);
//	9)、插入操做 
	/*
		L:順序表的指針
		i:須要插入到第幾個元素 
		x:插入元素的值 
	*/
int insert(seqList *L, DataType i, DataType x);
// 10)、按位刪除 
	/*
		L:順序表指針
		i:須要刪除第幾個元素 
		ptr:存儲刪除的元素 
	*/
int deleteByPosition(seqList *L, DataType i, DataType *ptr);

測試

/* 測試 */
int main()
{
	int arr[] = {3,2,8,4,9};
	int i;
	seqList L;
	creatList(&L, arr, 5);
	
	i = getLength(&L);
	printf("順序表長度:%d\n", i); 
	if(isEmpty)
	{
		printf("順序表非空\n");
	}
	printf("遍歷順序表:"); 
	printList(&L);
	printf("\n");
	
	int flag = locate(&L, 4);
	if(flag)
	{
		printf("查找成功,序號爲:%d\n", flag);
		
	}
	else
	{
		printf("查找失敗\n"); 
	} 
	
	int x;
	printf("請輸入你要查找元素的位置:");
	scanf("%d", &i);
	if(get(&L, i, &x))
	{
		printf("第%d個元素爲:%d\n", i,x);
	}
	
	if(insert(&L, 2, 22))
	{
		printf("插入元素後:");
		printList(&L);
		printf("\n"); 
	}
	
	int position, y; 
	printf("請輸入須要刪除元素的位置:\n");
	scanf("%d", &position);
	if(deleteByPosition(&L, position, &y))
	{
		printf("刪除的元素爲%d\t刪除元素後:", y);
		printList(&L);
		printf("\n"); 
	}
}

函數定義

/* 函數定義 */ 
void initList(seqList *L)
{
	L->length = 0;
} 

/*
	L :順序表的指針
	arr:傳入的數組
	n:須要創建的順序表的長度 
	
	建立成功返回 1,不然返回 0 
*/
int creatList(seqList *L, DataType arr[], int n)
{
	if(n > MaxSize)
	{
		printf("順序表的存儲空間不足,建立失敗!");
		return 0;
	}
	for(int i = 0; i< n; i++)
	{
		L->data[i] = arr[i];
	} 
	L->length = n;
	return 1;
}

int isEmpty(seqList *L)
{
	if(L->length == 0)
		return 1;
	else
		return 0; 
} 

int getLength(seqList *L)
{
	return L->length;
}

int printList(seqList *L)
{
	for(int i = 0; i< L->length; i++)
	{
		printf("%d\t", L->data[i]);
	}
}

int locate(seqList *L, DataType n)
{
	for(int i = 0; i< L->length; i++)
	{
		if(L->data[i] == n)
			return i+1;
	}
	return 0;
}

int get(seqList *L, DataType i, DataType *ptr)
{
	if(i < 1 || i > L->length)
	{
		printf("查找地址非法,查找失敗\n");
		return 0;
	}
	else
	{
		*ptr = L->data[i-1];
		return 1;
	}
}

int insert(seqList *L, DataType i, DataType x)
{
	if(L->length >= MaxSize) 
	{
		printf("上溢錯誤,插入失敗\n");
	}
	if(i < 1 || i > L->length+1)
	{
		printf("插入位置錯誤,插入失敗\n");
		return 0; 
	}
	for(int j = L->length; j>= i; j--)
	{
		L->data[j] = L->data[j-1];
	} 
	L->data[i-1] = x;
	L->length++;
	return 1;
}

int deleteByPosition(seqList *L, DataType i, DataType *ptr)	//  ?
{
	if(L->length == 0)
	{
		printf("下溢錯誤,刪除失敗\n");
		return 0;
	} 
	if(i < 0 || i > L->length )
	{
		printf("位置錯誤,刪除失敗\n");
		return 0; 
	}
	*ptr = L->data[i-1];
	for(int j = i; j< L->length; j++)
	{
		L->data[j-1] = L->data[j];
	}
	L->length--;
	return 1;
}

運行效果

輸入圖片說明

(二)單鏈表的實現

單鏈表的存儲結構定義

/* 單鏈表的存儲結構定義 */
typedef int DataType;
typedef struct Node 
{
	DataType data;
	struct Node *next;
} Node;

單鏈表的實現

函數聲明

/* 函數聲明 */ 

//	1)、初始化單鏈表
Node *initList();
//	2)、創建單鏈表
Node *creatList(DataType arr[], int n);
//	3)、銷燬單鏈表
void destroy(Node *first);
//	4)、判空操做
int isEmpty(Node *first);
//	5)、求單鏈表的長度
int getLength(Node *first);
//	6)、遍歷操做
void printList(Node *first);
//	7)、按值查找
int locate(Node *first, DataType n);
//	8)、按位查找
	/*
		L:單鏈表的指針
		i:須要查找第幾個元素 
		ptr:存儲查找到的元素 
	*/
int get(Node *first, DataType i, DataType *ptr);
//	9)、插入操做 
	/*
		L:單鏈表的指針
		i:須要插入到第幾個元素 
		x:插入元素的值 
	*/
int insert(Node *first, DataType i, DataType x);
// 10)、按位刪除 
	/*
		L:單鏈表指針
		i:須要刪除第幾個元素 
		ptr:存儲刪除的元素 
	*/
int deleteByPosition(Node *first, DataType i, DataType *ptr);

測試

/* 測試 */
int main()
{
	int arr[] = {1,2,3,4,5};
	Node *first = NULL;
	first = creatList(arr, 5);
	
	printf("單鏈表的長度:%d\n", getLength(first)); 
	
	printf("遍歷單鏈表:"); 
	printList(first);
	printf("\n");
	
	int x,flag;
	printf("請輸入要查找的元素:");
	scanf("%d", &x); 
	flag = locate(first, x);
	if(flag)
		printf("查找成功,序號爲%d\n", flag);
	else 
		printf("查找失敗\n");
	
	int locatePos, y;
	printf("請輸入你要查找的位置:");
	scanf("%d", &locatePos);
	if(get(first, locatePos, &y))
		printf("查找成功,第%d個元素爲:%d\n", locatePos,y);
		
	int insertPos, insertValue;
	printf("請輸入插入元素的位置:");
	scanf("%d", &insertPos); 
	if(insert(first, insertPos, 33))
	{
		printf("插入成功,插入後遍歷單鏈表:");
		printList(first); 
		printf("\n");
	}
	
	int deletePos, z;
	printf("請輸入你要刪除的位置:");
	scanf("%d", &deletePos);
	if(deleteByPosition(first, deletePos, &z))
	{
		printf("刪除第%d個元素%d成功,刪除後遍歷單鏈表:\n", deletePos,z);
		printList(first); 
		printf("\n"); 
	}	
	
	destroy(first);
	
	if(isEmpty(first))
	{
		printf("單鏈表已銷燬");
	}
}

函數定義

/* 函數定義 */

Node *initList()
{
	Node *first = (Node *)malloc(sizeof(Node));
	first->next = NULL;
	return first;
}

//頭插法建立單鏈表:每次新申請的節點插在頭結點以後 
Node *creatList(DataType arr[], int n)
{
	Node *s = NULL;
	Node *first = (Node *)malloc(sizeof(Node));
	first->next = NULL;
	for(int i = 0; i< n; i++)
	{
		s = (Node *)malloc(sizeof(Node));
		s->data = arr[i];
		s->next = first->next; first->next = s; 
	}
	return first;
}

int isEmpty(Node *first)
{
	if(first->next)
		return 1;
	else 
		return 0;
}

int getLength(Node *first)
{
	Node *p = first->next;	//工做指針p初始化 
	int length = 0;
	while(p != NULL)
	{
		p = p->next;
		length++;
	}
	return length;
}

void printList(Node *first)
{
	Node *p = first->next;
	while(p != NULL)
	{
		printf("%d\t", p->data);
		p = p->next;
	}
}

int locate(Node *first, DataType n)
{
	int flag = 0;
	Node *p = first->next;
	while(p != NULL)
	{
		if(p->data == n)
		{
			return flag+1;
		}
		p = p->next;
		flag++;
	}
	return 0;
}

int get(Node *first, DataType i, DataType *ptr)
{
	Node *p = first->next;
	int count = 1;
	while(p != NULL && count < i)
	{
		p = p->next;
		count++;
	}
	if(p == NULL)
	{
		printf("位置錯誤,查找失敗\n");
		return 0;
	}
	else
	{
		*ptr = p->data;
		return 1;
	} 
}

int insert(Node *first, DataType i, DataType x)
{
	Node *p = first;
	Node *s = NULL;
	int count = 0;
	while(p != NULL && count < i-1)
	{
		p = p->next;
		count++;
	} 
	if(p == NULL)
	{
		printf("位置錯誤,插入失敗\n");
		return 0;
	}
	else
	{
		s = (Node *)malloc(sizeof(Node));
		s->data = x;
		s->next = p->next; p->next = s;
		return 1; 
	}
} 

int deleteByPosition(Node *first, DataType i, DataType *ptr)
{
	Node *p = first;
	Node *q = NULL;
	int count = 0;
	while(p != NULL && count < i-1)
	{
		p = p->next;
		count++;
	}
	if(p == NULL || p->next == NULL)
	{
		printf("位置錯誤,刪除失敗\n");
		return 0;
	}
	else
	{
		q = p->next; p->next = q->next;
		*ptr = q->data;
		free(q);
		return 1;
	}
}

void destroy(Node *first)
{
	Node *p = first;
	while(first != NULL)
	{
		first = first->next;
		free(p);
		p = first;
	}
}

運行效果

輸入圖片說明

(三)順序表和鏈表的比較

時間性能比較

  1. 訪問元素優點——順序表: 取出線性表的第i個元素這種操做,使用順序表更快一些,其時間複雜度爲O(1);單鏈表的時間複雜度爲O(n),由於它只能從表頭開始依次向後掃描。
  2. 插入、刪除元素優點——鏈表: 在鏈表總插入和刪除元素不須要移動元素,其時間複雜度爲O(1);在順序表中插入和刪除操做須要移動元素,其平均時間複雜度爲O(n),當元素較多時,移動元素的時間開銷很大。

通常規律:

​ 若線性表需頻繁查找卻不多進行插入和刪除操做,或者操做和「數據元素在線性表中的位置「密切相關時,宜採用順序表做爲存儲結構;反之,宜採用鏈表做爲存儲結構。數組

空間性能比較

  1. 鏈表中須要指針的結構性開銷
  2. 順序表存儲長度須要事先固定,而鏈表無此限制

通常規律:

​ 當線性表中的元素個數變化較大或者未知時,最好使用鏈表實現;若是事先已知線性表的大體長度,使用順性表的空間效率會更高。數據結構

結語

注:運行代碼須要補上頭文件函數

學習博客:結構體 :http://blog.csdn.net/ly666888555/article/details/52206973性能

參考書籍:《數據結構——從概念到C實現》學習

相關文章
相關標籤/搜索