线性表的顺序存储设计与实现(C语言版本)

 
 
//向一个线性表list的pos位置处插入新元素node
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos)
{
	int ret = 0;
	//1 缓存下来 进行操作
	TSeqList *tmp = NULL;
	if (NULL == list || NULL == node || pos < 0)
	{
		ret = -1;
		printf("func err NULL == list || NULL == node || pos < 0:%d\t", ret);
		return ret;
	}
	tmp = (TSeqList *)list;
	//注意1:线性表长度应该小于等于数组的长度
	if (tmp->length >=tmp->capacity)
	{
		ret = -2;
		printf("func err tmp->length >=tmp->capacity:%d\t", ret);
		return ret;
	}
	//注意2:容错修正 假设容量为20,此时线性表长度为6,pos却为10,这个时候可以做容错修正,直接修正为尾插法
	if (pos > tmp->length)
	{
		pos = tmp->length;
	}
	//2 元素后移
	int i;
	for ( i = tmp->length; i > pos; i--)
	{
		//t[3]=t[2];
		tmp->node[i] = tmp->node[i-1];//后移
	}
	//3 空出位置 插入新结点
	tmp->node[i] = (unsigned int)node;
	//4 线性表长度+1
	tmp->length++;

	return 0;
}


//删除一个线性表list的pos位置处的元素  返回值为被删除的元素,NULL表示删除失败
SeqListNode* SeqList_Delete(SeqList* list, int pos)
{
	int ret = 0;
	//1 缓存下来 进行操作
	TSeqList *tmp = NULL;
	TSeqList *Deletemp = NULL;
	if (NULL == list || pos < 0)
	{
		ret = -1;
		printf("func err NULL == list  || pos < 0:%d\t", ret);
		return NULL;
	}
	tmp = (TSeqList *)list;

	Deletemp = (SeqListNode *)tmp->node[pos];//缓存下来要删除的元素
	//2 元素前移
	for (int i = pos + 1; i < tmp->length; i++)
	{
		//t[1]=t[2]
		tmp->node[i - 1] = tmp->node[i];
	}
	//3 删除元素后 线性表长度减1
	tmp->length--;

	return Deletemp;
}

线性表顺序存储设计与实现详细代码如下:

//线性表顺序存储设计与实现测试框架
//SeqList.h
#ifndef _SEQLIST_H_
#define _SEQLIST_H_

typedef void SeqList;
typedef void SeqListNode;
/*
这两句话意思:
C语言里面的typedef,字面上理解就是类型的定义,也就是给内置的或自定义的数据类型重新命名
typedef void SeqList; 等价于下面void* ===》SeqList*
typedef void SeqListNode;下面代码SeqListNode* 等价于void *
typedef void SeqList; 给void起别名为 SeqList
typedef void SeqListNode;
这样做是为了使用者方便阅读,

SeqList* SeqList_Create(int capacity); //这样一看返回值就知道是返回值是链表
void * SeqList_Create(int capacity); //如果这样,使用者一看只知道是返回指针,不知道具体的,可读性很差
所以才会给void起别名,封装好的底层函数,提供给使用者使用,使用者会给容易懂
*/



//创建并且返回一个空的线性表
SeqList* SeqList_Create(int capacity);

//销毁一个线性表list
void SeqList_Destroy(SeqList* list);

//将一个线性表list中的所有元素清空, 线性表回到创建时的初始状态
void SeqList_Clear(SeqList* list);

//返回一个线性表list中的所有元素个数
int SeqList_Length(SeqList* list);

//返回一个线性表list中的容量
int SeqList_Capacity(SeqList* list);

//向一个线性表list的pos位置处插入新元素node
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos);

//获取一个线性表list的pos位置处的元素
SeqListNode* SeqList_Get(SeqList* list, int pos);

//删除一个线性表list的pos位置处的元素  返回值为被删除的元素,NULL表示删除失败
SeqListNode* SeqList_Delete(SeqList* list, int pos);



#endif  //
//SeqList.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SeqList.h"

//在结构体中套一级指针
typedef struct _tag_SeqList
{
	int length;//线性表的长度
	int capacity;//数组的长度-存放线性表的存储空间的长度
	unsigned int *node;//链表需要有内存空间存储装元素-根据容量来分配内存空间-需要动态分配内存空间
}TSeqList;



//创建并且返回一个空的线性表
SeqList* SeqList_Create(int capacity)
{
	int ret = 0;
	//1 线性表申请动态内存空间
	TSeqList *tmp = NULL;
	tmp = (TSeqList *)malloc(sizeof(TSeqList));
	if (NULL == tmp)
	{
		ret = -1;
		printf("func err malloc:%d\t",ret);
		return NULL;
	}
	memset(tmp,0,sizeof(TSeqList));//让开辟的内存 完成线性表初始化
	//2 根据容量分配内存大小
	tmp->node = (unsigned int )malloc(sizeof(unsigned int *)*capacity);
	if (NULL == tmp->node)
	{
		ret = -2;
		printf("func err malloc:%d\t", ret);
		return NULL;
	}
	tmp->capacity = capacity;
	tmp->length = 0;

	return tmp;
}

//销毁一个线性表list
//小心先开辟内存空间的后释放
void SeqList_Destroy(SeqList* list)
{
	int ret = 0;
	//1 缓存下来 进行操作
	TSeqList *tmp = NULL;
	if (NULL == list)
	{
		ret = -1;
		printf("func err SeqList_Destroy:%d\t", ret);
	}
	tmp = (TSeqList *)list;

	//先申请 后释放
	if (tmp->node!=NULL)
	{
		free(tmp->node);
	}
	free(tmp);
}

//将一个线性表list中的所有元素清空, 线性表回到创建时的初始状态
void SeqList_Clear(SeqList* list)
{
	int ret = 0;
	//1 缓存下来 进行操作
	TSeqList *tmp = NULL;
	if (NULL == list)
	{
		ret = -1;
		printf("func err SeqList_Clear:%d\t", ret);
	}
	tmp = (TSeqList *)list;
	tmp->length = 0;
	memset(tmp->node, 0, tmp->capacity * sizeof(unsigned int *));//重新将线性表中创建的结点初始化
}

//返回一个线性表list中的所有元素个数
int SeqList_Length(SeqList* list)
{
	int ret = 0;
	//1 缓存下来 进行操作
	TSeqList *tmp = NULL;
	if (NULL == list)
	{
		ret = -1;
		printf("func err SeqList_Length:%d\t", ret);
		return ret;
	}
	tmp = (TSeqList *)list;
	return tmp->length;
}

//返回一个线性表list中的容量
int SeqList_Capacity(SeqList* list)
{
	int ret = 0;
	//1 缓存下来 进行操作
	TSeqList *tmp = NULL;
	if (NULL == list)
	{
		ret = -1;
		printf("func err SeqList_Capacity NULL == list:%d\t", ret);
		return ret;
	}
	tmp = (TSeqList *)list;
	return tmp->capacity;
}

//向一个线性表list的pos位置处插入新元素node
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos)
{
	int ret = 0;
	//1 缓存下来 进行操作
	TSeqList *tmp = NULL;
	if (NULL == list || NULL == node || pos < 0)
	{
		ret = -1;
		printf("func err NULL == list || NULL == node || pos < 0:%d\t", ret);
		return ret;
	}
	tmp = (TSeqList *)list;
	//注意1:线性表长度应该小于等于数组的长度
	if (tmp->length >=tmp->capacity)
	{
		ret = -2;
		printf("func err tmp->length >=tmp->capacity:%d\t", ret);
		return ret;
	}
	//注意2:容错修正 假设容量为20,此时线性表长度为6,pos却为10,这个时候可以做容错修正,直接修正为尾插法
	if (pos > tmp->length)
	{
		pos = tmp->length;
	}
	//2 元素后移
	int i;
	for ( i = tmp->length; i > pos; i--)
	{
		//t[3]=t[2];
		tmp->node[i] = tmp->node[i-1];//后移
	}
	//3 空出位置 插入新结点
	tmp->node[i] = (unsigned int)node;
	//4 线性表长度+1
	tmp->length++;

	return 0;
}

//获取一个线性表list的pos位置处的元素
SeqListNode* SeqList_Get(SeqList* list, int pos)
{
	int ret = 0;
	//1 缓存下来 进行操作
	TSeqList *tmp = NULL;
	if (NULL == list || pos < 0)
	{
		ret = -1;
		printf("func err NULL == list  || pos < 0:%d\t", ret);
		return NULL;
	}
	tmp = (TSeqList *)list;
	tmp = (SeqListNode *)tmp->node[pos];
	return tmp;
}

//删除一个线性表list的pos位置处的元素  返回值为被删除的元素,NULL表示删除失败
SeqListNode* SeqList_Delete(SeqList* list, int pos)
{
	int ret = 0;
	//1 缓存下来 进行操作
	TSeqList *tmp = NULL;
	TSeqList *Deletemp = NULL;
	if (NULL == list || pos < 0)
	{
		ret = -1;
		printf("func err NULL == list  || pos < 0:%d\t", ret);
		return NULL;
	}
	tmp = (TSeqList *)list;

	Deletemp = (SeqListNode *)tmp->node[pos];//缓存下来要删除的元素
	//2 元素前移
	for (int i = pos + 1; i < tmp->length; i++)
	{
		//t[1]=t[2]
		tmp->node[i - 1] = tmp->node[i];
	}
	//3 删除元素后 线性表长度减1
	tmp->length--;

	return Deletemp;
}
//线性表顺序存储设计与实现测试框架
//text.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SeqList.h"

//业务结点
typedef struct _Teacher
{
	char name[32];
	int age;
}Teacher;

int main()
{
	int ret = 0;
	Teacher t1, t2, t3;
	t1.age = 31;
	t2.age = 32;
	t3.age = 33;

	//1创建空的线性表的顺序存储结构
	SeqList *list = NULL;
	list = SeqList_Create(10);
	if (NULL == list)
	{
		ret = -1;
		printf("func err SeqList_Create():%d\n",ret);
		return ret;
	}
	//2 插入元素 线性表的插入 采用头插法
	ret = SeqList_Insert(list,(SeqListNode *)&t1,0);
	if (ret!=0)
	{
		ret = -2;
		printf("func err SeqList_Insert():%d\n", ret);
		return ret;
	}
	ret = SeqList_Insert(list, (SeqListNode *)&t2, 0);
	ret = SeqList_Insert(list, (SeqListNode *)&t3, 0);

	//3 遍历线性表
	for (int i = 0; i < SeqList_Length(list); i++)
	{
		Teacher *tmp = (Teacher *)SeqList_Get(list,i);//获取链表结点的位置
		if (NULL == tmp)
		{
			ret = -3;
			printf("func err SeqList_Get():%d\n", ret);
			return ret;
		}
		printf("age:%d\t",tmp->age);
	}

	//4 删除线性表结点
	while (SeqList_Length(list) > 0)
	{
		Teacher *tmp = (Teacher *)SeqList_Delete(list,0);
		if (NULL == tmp)
		{
			ret = -4;
			printf("func err SeqList_Delete():%d\n", ret);
			return ret;
		}
		printf("age:%d\t", tmp->age);
	}

	//5 销毁线性表
	SeqList_Destroy(list);

	system("pause");
	return 0;
}

线性表的顺序存储结构,在存,读数据时,不管是哪个位置,时间复杂度都是O(1),而插入或删除元素时候,时间复杂度是O(n)。这就说明比较适合元素个数不太变化,而更多是存取元素的应用.

线性表顺序存储结构的优缺点

 长处:1、无须为表示表中元素之间的逻辑关系而添加额外的存储空间。

             2、能够高速的存取表中任一位置的元素。

 缺点:1、插入和删除操作须要移动大量的元素。

          2、当线性表长度变化较大时,难以确定存储空间的容量。

          3、造成存储空间的“碎片”。

========================================

  但是有一点须要注意,能够高速的存取表中任一位置的“存”,和“插入”有什么差别呢?

“存”的意思表达的就是给线性表的任何位置赋值,表达为程序代码为 arr[3] = 100;

 "插入"的意思表达的是在第i个位置插入一个元素。

比方插入线性表的第三个位置,就是第三个元素后的每一个元素都要向后移动一位(数组的长度假定够长)。

for(int i=3;i<10;i++){

arr[i+i] = arr[i];

}

这就说明线性顺序存储结构比較适合元素个数不太变化。而很多其它的是存取数据的应用。


线性表的顺序存储结构理解:

实现底层算法与业务结点的分离,采用的是插入的结点,像二维数组的行元素,每个行元素指向一个Teacher的结构体,故你插入多少条信息都是可以的

//线性表顺序存储设计与实现测试框架
//SeqList.h

#ifndef _SEQLIST_H_
#define _SEQLIST_H_

typedef void SeqList;
typedef void SeqListNode;

//这两句话意思:
//C语言里面的typedef, 字面上理解就是类型的定义, 也就是给内置的或自定义的数据类型重新命名
//SeqList* SeqList_Create(int capacity); //这样一看返回值就知道是返回值是链表
//void * SeqList_Create(int capacity); //如果这样,使用者一看只知道是返回指针,不知道具体的,可读性很差
//所以才会给void起别名,封装好的底层函数,提供给使用者使用,使用者会给容易懂


//创建并且返回一个空的线性表
SeqList* SeqList_Create(int capacity);

//销毁一个线性表list
void SeqList_Destroy(SeqList* list);

//将一个线性表list中的所有元素清空, 线性表回到创建时的初始状态
void SeqList_Clear(SeqList* list);

//返回一个线性表list中的所有元素个数
int SeqList_Length(SeqList* list);

//返回一个线性表list中的容量
int SeqList_Capacity(SeqList* list);

//向一个线性表list的pos位置处插入新元素node
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos);

//获取一个线性表list的pos位置处的元素
SeqListNode* SeqList_Get(SeqList* list, int pos);

//删除一个线性表list的pos位置处的元素  返回值为被删除的元素,NULL表示删除失败
SeqListNode* SeqList_Delete(SeqList* list, int pos);


#endif
//SeqList.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SeqList.h"


//在结构体中套一级指针
typedef struct _tag_SeqList
{
	int length;//线性表的长度
	int capacity;//数组的长度-存放线性表的存储空间的长度
	unsigned int *node;//链表需要有内存空间存储装元素-根据容量来分配内存空间-需要动态分配内存空间  int node[]
}TSeqList;


//创建并且返回一个空的线性表
SeqList* SeqList_Create(int capacity)
{
	int ret = 0;
	if (capacity <= 0)
	{
		ret = -1;
		printf("func err (capacity <= 0):%d\t", ret);
		return NULL;
	}
	//1 线性表申请动态内存空间
	TSeqList *tmp = (TSeqList *)malloc(sizeof(TSeqList));//开辟一片内存空间,大小是TSeqList类这么大
	if (NULL == tmp)
	{
		ret = -2;
		printf("func err malloc:%d\t", ret);
		return NULL;
	}
	//开辟的内存,完成初始化
	memset(tmp,0,sizeof(TSeqList));

	//2 根据容量分配内存大小
	tmp->node = (unsigned int *)malloc(sizeof(unsigned int)*capacity);//创建node结点的内存空间大小-相当于二维数组的行元素个数
	if (NULL == tmp->node)
	{
		ret = -3;
		printf("func err malloc:%d\t", ret);
		return NULL;
	}
	tmp->capacity = capacity;
	tmp->length = 0;

	return tmp;
}

//销毁一个线性表list
void SeqList_Destroy(SeqList* list)
{
	int ret = 0;
	if (NULL == list)
	{
		ret = -1;
		printf("func err (NULL == list):%d\t", ret);
	}
	//1 缓存下来 进行操作
	TSeqList *tmp = NULL;
	tmp = (TSeqList *)list;
	//2 先申请 后释放
	if (tmp->node != NULL)
	{
		free(tmp->node);
	}
	if (tmp!=NULL)
	{
		free(tmp);
	}
}


//将一个线性表list中的所有元素清空, 线性表回到创建时的初始状态
void SeqList_Clear(SeqList* list)
{
	int ret = 0;
	if (NULL == list)
	{
		ret = -1;
		printf("func err (NULL == list):%d\t", ret);
	}
	//1 缓存下来 进行操作
	TSeqList *tmp = NULL;
	tmp = (TSeqList *)list;
	//2 线性表中的长度置空
	tmp->length = 0;
	//3 重新将线性表中创建的结点初始化
	memset(list,0,tmp->capacity * sizeof(unsigned int)); // 会把所有的置空
}


//返回一个线性表list中的所有元素个数
int SeqList_Length(SeqList* list)
{
	int ret = 0;
	if (NULL == list)
	{
		ret = -1;
		printf("func err (NULL == list):%d\t", ret);
		return ret;
	}
	//1 缓存下来 进行操作
	TSeqList *tmp = NULL;
	tmp = (TSeqList *)list;

	return tmp->length;
}


//返回一个线性表list中的容量
int SeqList_Capacity(SeqList* list)
{
	int ret = 0;
	if (NULL == list)
	{
		ret = -1;
		printf("func err (NULL == list):%d\t", ret);
		return ret;
	}
	//1 缓存下来 进行操作
	TSeqList *tmp = NULL;
	tmp = (TSeqList *)list;
	return tmp->capacity;
}


//向一个线性表list的pos位置处插入新元素node
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos)
{
	int ret = 0;
	if (NULL == list || NULL == node||pos < 0)
	{
		ret = -1;
		printf("func err (NULL == list || NULL == node||pos < 0):%d\t", ret);
		return ret;
	}
	//1 缓存下来 进行操作
	TSeqList *tmp = NULL;
	tmp = (TSeqList *)list;
	//注意1:线性表长度应该小于等于数组的长度
	if (tmp->length >=tmp->capacity)
	{
		ret = -2;
		printf("func err (tmp->length >=tmp->capacity):%d\t", ret);
		return ret;
	}
	//注意2:容错修正 假设容量为20,此时线性表长度为6,pos却为10,这个时候可以做容错修正,直接修正为尾插法
	if (pos >tmp->length)
	{
		pos = tmp->length;
	}
	//2 元素后移
	int i;
	for ( i = tmp->length; i > pos; i--)
	{
		tmp->node[i] = tmp->node[i - 1];//后移
		//t[pos+1] = t[pos+1-1]=t[pos]
	}
	//3 空出的位置插入新结点
	tmp->node[i] = (unsigned int )node;//这里装二维数组的行的一个元素,这个行元素指向业务结点teacher这个结构体,所以teacher里面装多少信息,都是可以的
	//4 线性表长度+1
	tmp->length++;

	return ret;
}


//获取一个线性表list的pos位置处的元素
SeqListNode* SeqList_Get(SeqList* list, int pos)
{
	int ret = 0;
	if (NULL == list || pos < 0)
	{
		ret = -1;
		printf("func err (NULL == list || pos < 0):%d\t", ret);
		return NULL;
	}
	//1 缓存下来 进行操作
	TSeqList *tmp = NULL;
	tmp = (TSeqList *)list;
	//获取一个线性表list的pos位置处的元素
	tmp = (SeqListNode *)tmp->node[pos];

	return tmp;
}


//删除一个线性表list的pos位置处的元素  返回值为被删除的元素,NULL表示删除失败
SeqListNode* SeqList_Delete(SeqList* list, int pos)
{
	int ret = 0;
	if (NULL == list || pos < 0)
	{
		ret = -1;
		printf("func err (NULL == list || pos < 0):%d\t", ret);
		return NULL;
	}
	//1 缓存下来 进行操作
	TSeqList *tmp = NULL;
	tmp = (TSeqList *)list;

	//2 缓存删除元素
	TSeqList *Deletemp = NULL;
	Deletemp = (SeqListNode *)tmp->node[pos];

	//3 前移
	for (int i = pos+1; i < tmp->length; i++)
	{
		tmp->node[i-1] = tmp->node[i];
	}
	//4 删除元素后 线性表长度减1
	tmp->length--;

	return Deletemp;
}
//线性表顺序存储设计与实现测试框架
//text.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SeqList.h"

//业务结点

typedef struct _Tag_Teacher
{
	int name;
	int age;
	int age1;
	double aa;
	double bb;
	double cc;
	double dd;
	double ee;
}Teacher;

int main()
{
	int ret = 0;
	Teacher t1, t2, t3;
	t1.age = 11;
	t1.name = 11;
	t1.age1 = 11;
	t1.aa = 11;
	t1.bb = 11;
	t1.cc = 11;
	t1.dd = 11;
	t1.ee = 11;

	//t2.age = 12;
	//t2.name = "shao12";
	//t2.aa = 11;

	//t3.age = 13;
	//t3.name = "shao13";
	//t3.aa = 11;

	//1 创建空的线性表的顺序存储结构
	SeqList *list = NULL;
	list = SeqList_Create(1);
	if (NULL == list)
	{
		ret = -1;
		printf("func err SeqList_Create():%d\n", ret);
		return ret;
	}
	//2 插入元素 线性表的插入 采用头插法
	ret = SeqList_Insert(list,(SeqListNode *)&t1,0);
	if (ret!=0)
	{
		ret = -2;
		printf("func err SeqList_Insert():%d\n",ret);
		return ret;
	}

	//清除链表
	//SeqList_Clear(list);
	ret = SeqList_Capacity(list);
	printf("func SeqList_Capacity():%d\n", ret);

	ret = SeqList_Insert(list, (SeqListNode *)&t1, 0);
	ret = SeqList_Insert(list, (SeqListNode *)&t2, 0);
	ret = SeqList_Insert(list, (SeqListNode *)&t3, 0);

	//3 遍历线性表
	for (int i = 0; i < SeqList_Length(list);i++)
	{
		Teacher *temp = (Teacher *)SeqList_Get(list,i);
		if (NULL == temp)
		{
			ret = -3;
			printf("func err SeqList_Get():%d\n", ret);
			return ret;
		}
		//printf("Teacher age:%d\t",temp->age);
		printf("年龄:%d,name:%d,naa:%f", temp->age,temp->name,temp->ee);

	}
	//4 删除线性表结点
	while (SeqList_Length(list) > 0)
	{
		Teacher *temp = (Teacher *)SeqList_Delete(list,0);
		if (NULL == temp)
		{
			ret = -4;
			printf("func err SeqList_Delete():%d\n", ret);
			return ret;
		}
		//printf("Teacher age:%d\t", temp->age);
		printf("年龄:%d,name:%d,naa:%f", temp->age, temp->name, temp->ee);

	}
	//5 销毁链表
	SeqList_Destroy(list);
	

	printf("Teacher age:%d\t", sizeof(unsigned int));//sizeof(unsigned int) 4 32

	printf("Teacher age:%d\t", sizeof(unsigned int*));//指针在32位编译器中是4个字节,在64位是8个字节
	system("pause");
	return ret;
}





猜你喜欢

转载自blog.csdn.net/weixin_40807247/article/details/80315373
今日推荐