顺序表、单链表——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实现》学习

相关文章
相关标签/搜索