顺序表的定义,初始化,加工(插入,删除,修改),引用(遍历,查找),实例

线性表

抽象数据类型定义形式:

ADT List
{
数据对象
数据关系;
基本操作;{初始化操作;销毁操作;引用类型操作;加工型操作;}
}

顺序储存

用一组连续的储存空间存放线性表中的各个数据元素,用位置相邻的储存空间关系白哦是线性表中数据元素的前驱和后继关系;

建立

定义时需包括:

  1. 一片连续的存储空间(数组或数组的起始位置)
  2. 容量(数组的大小,防止溢出)
  3. 长度(已存入数据个数)
//方一,直接定义数组    常用!需掌握!
#define MAX 100
typedef struct
{
    ElemType data[MAX];    //ElemType表示数据元素的抽象类型
    int listSize;
    int length;
}SqList;    //顺序表,结构体数据类型

//方二:定义数组起始地址的指针变量    更灵活!难理解一些学有余力建议使用!
typedef struct
{
    ElemType *data;
    int size;
    int length;
} SqList;

当你的顺序表存储的东西比较复杂,比如一组学生数据时,你可以这样做:

//先定义学生数据的数据类型
typedef struct
{
    char name[20];    //姓名
    char no[20];    //学号
    float score;    //成绩
}STD;
//再定义顺序表数据类型
// typedef STD ElemType;    有时候会将STD重命名为ElemType
typedef struct
{
    STD *data;    //这里的STD就是上面的ElemType对应的实际数据类型
    int listsize;
    int length;
}SqList;    //现在顺序表里的一个元素就是一个指向STD类型的指针变量

使用:

SqList L, *p = &L;    //p指向L

在访问结构体变量的成员时,有两种访问方式:结构体变量访问(L.data[i]),和指针变量访问(p->data[i])
顺序表建立好后,我们对其进行操作就是在通过参数进行数据的传递,同样两种情况

  • 调用函数只读不影响实参
  • 调用函数改变实参

简单来说,就是前者只是分享数据,后者是需要修改main方法中的数据(比如我们现在要做的),后者通过指针传递实参地址来实现

初始化

//使用int定义函数,返回函数值可以提高操作的健壮性
int initList(SqList *L, int max)
{
   L->data = (STD* )malloc(max *sizeof(STD));
   //不改变数组大小的话
   //L->data = (STD* )malloc(sizeof(STD));
   //直接new一个数组也是可以的
   //L->data = new int[MAX];
   if(L->data == NULL)(printf("空间申请失败!");return 0;}
   L->listSize = max;
   L->length = 0;
   return 1;
}
//或者
int initList(SqList &L, int max)
{
   L.data = (STD* )malloc(max *sizeof(STD));
   ...
}

调用时:

int main()
{
    SqList L;
    if(initList(&L,10))printf("创建成功!");    //创建一个大小为10的顺序表
    else{
    printf("创建失败!");
    exit(0);    //创建失败就退出程序,不必要但是个好习惯
    }
}
//第二种
if(initList(L,10)printf("创建成功!");

这两种方法各有什么优缺点呢,还需要组织一下语言,争取下次更新的时候补上OTZ
初始化就是申请了一片连续的存储空间,给成员变量赋予了初值
理论上来说new 和malloc 都是可以的,但是一般都用malloc (要配合free()使用),同样下次更新分析

关于malloc函数的参考资料:
[1]https://www.cnblogs.com/Commence/p/5785912.html.
[2]https://blog.csdn.net/qq_27871973.

加工型操作

改变线性表本身
初始条件是线性表已存在

  • 置空
  • 插入
  • 删除
  • 修改
置空
插入

将新数据插入指定位置,线性表长度加一

int insertList(SqList *L,int i,ElemType e)    //传递数据的指针,插入位置,插入数据
{
    int k;
    if(i<1||i>L->length + 1) {printf("插入位置异常!\n");return 0;}    //判读插入位置是否合理
    if(L->length>=L->ListSize){printf("数据溢出!\n");return 0;}    //判断顺序表是否已满
    for(k = L->length;k>=i;k--)
        L->data[k] = L->data[k-1];    //将插入位置后的数据全部后移一位
    L->data[i-1] = x;    //插入数据
    L->length = L->length + 1;    //表长加一
    return 1;
}

排序插入,不指定位置

int insertList(SqList *L, ElemType e) {
	if (L->length == ListSize) 
	{
	    printf("数据溢出,无法操作!\n");
	    return 0;
	}    //判断是否已满
	else if(L->length== 0)
	{
		L->data[0] = e;    //第一个数据,不需要排序
		L->length++;
		return 1;
	}
	else {
		int j;
		j = p->length;
		p->elem[j] = e;
		while(j > 0 && p->elem[j-1].year > e.year){
			p->elem[j] = p->elem[j-1];
			p->elem[j-1] = e;
			j--;	
		}
		p->length++;
		return 1;                                                                                                                                                                                      
	}
}
删除

删除指定位置的数据

int deleteList(SqList *L,int i,ElemType e)    //传递数据的指针,插入位置,插入数据
{
    ...    //判断语句
    *e = L->data[i-1];
    for(int k = i;k<L->length;k++)
        L->data[k -1] = L->data[k];    //将删除位置前的数据全部前移一位,最后一位i = L->length-1删除不需要前移
    L->length = L->length - 1;    //表长减一
    return 1;
}

调用:

int main()
{ 
    ElemType e;
    if(deleteList(&L,2,&e))
       printf("删除的数据为:%s%s%d\n");
// 如果不需要打印,去掉参数e就好
    else
        printf("删除失败!");
}
修改

将指定位置的数据修改为新数据

int reviseList(SqList *L,int i,ElemType *e)
{
    ...   //判断
    L.data[i-1] = e;
    return 1;
}

调用:

int main()
{
    ElemType e = {"张三","007",99};   //不同的赋值方式
    e.name = "张三";
    strcpy(e.no,"007");    //这样给字符串赋值也可以
    e.score = 99;
    if(reviseList(&L,2,&x)) printf("修改成功!");
    else printf("修改失败!");
}

引用型操作

只使用线性表中的元素,但并没有改变线性表本身
初始条件是线性表已存在

  • 判断是否为空
  • 求长度
  • 按位读取
  • 按值求位
  • 遍历(输出)
判断是否为空&&求长度
L->length
按位获取
int getList(SqList *L,int i,ElemType *e)
{
    ...  //判断
    *e = L->data[i-1];
    return 1;
}

调用:

int main()
{
    ElemType e;
    if(getList(&L,2,&e))
       printf("获取的数据是%s %s %d\n",e.name,e.no,e.score);
    else ...
}
定位
int locationList(SqList *L,char *x)
{
    int i;
    if(L->length == 0) {printf("没有数据!");return 0;} 
    for(int i = 0;i<L->length;i++)
        if(strcmp(L->data[i].name,x) == 0)
            return i + 1;
    return 0;
}

调用:

int main()
{
    ElemType e;
    if(locationList(&L,e.name) != 0)
        printf("在第%d个位置上找到!",locationList(&L,e.name));
    else ...
}
遍历(打印)
int print(SqList *L)
{
    for(int i = 0;i<L->length;i++)
        printf("%s\n",L->data[i].name);
    return 1;
}
  • 时间复杂度
    T(n) = O(1),没有涉及循环:初始化,修改、获取
    T(n) = O(n):插入、删除、定位、遍历

实例

设计顺序表,实现中国超算发展历史知识的管理,功能可以包括:创建,查找,增加,删除,修改,遍历输出,初始化,等。

#include<stdio.h>
#include<string.h>
#define MAXSIZE 100
typedef struct
{
	char name[20];
	char people[30];
	int year;
}BOOK;
typedef BOOK ElemType;
typedef struct
{
	ElemType* elem;
	int length;
	int listsize;
}SqList;
//初始化创建一个空表
void InitList(SqList *p)
{
	p->elem = new ElemType[MAXSIZE];
	p->length = 0;
	p->listsize = 100;
}
//排序插入 
int  ListInsert(SqList *p, ElemType e) {
	if (p->length == MAXSIZE)
		return 0;
	else if (p->length == 0) {
		p->elem[0] = e;
		p->length++;
		return 1;
	}
	else {
		int j;
		j = p->length;
		p->elem[j] = e;
		while(j > 0 && p->elem[j-1].year > e.year){
			p->elem[j] = p->elem[j-1];
			p->elem[j-1] = e;
			j--;	
		}
		p->length++;
		return 1;
	}
}
//任意位置删除
int ListDelete(SqList *p, int n) {
	if ((n < 0) || (n >= p->length))
		return 0;
	else {
		for (int j = n; j <= p->length - 1; j++)
			p->elem[j - 1] = p->elem[j];
		p->length--;
		return 1;
	}
}
//定位
int locationList(SqList *p,char *x)
{
    int i;
    if(p->length == 0) {printf("没有数据!");return 0;} 
    for(int i = 0;i<p->length;i++)
        if(strcmp(p->elem[i].name,x) == 0)
            return i + 1;
    return 0;
}
//按指定位置查找
int LocateElem(SqList* p, int i, ElemType *e) {
	if (i < 0 || i > p->length)
		return 0;
	else
    {
    	*e = p->elem[i-1];
		return 1;	
    }
}
//修改某条记录
int ReviseElem(SqList* p,int i,ElemType e)
{
	if (i < 0 || i >= p->length)
		return 0;
	else
	{
		p->elem[i] = e;
		return 1;
	}
}
//输出顺序表
void PrintList(SqList *p) {
	for (int i = 0; i < p->length; i++) 
		printf("姓名 : %s 开发人员 : %s 年份 : %d\n", p->elem[i].name, p->elem[i].people, p->elem[i].year);
}
//创建
int creatList(SqList* L)
{
	int n = 0;
	ElemType e;
	char yn;
	InitList(L);
	do
	{
		printf("请输入超算发展历史数据,用空格隔开:");
		scanf("%s %s %d", &e.name, &e.people, &e.year);
		getchar();
		ListInsert(L, e);
		n++;
		printf("是否继续输入?Y/N");
		yn = getchar();
	} while (yn == 'Y' || yn == 'y');
}
int main()
{
	printf("欢迎使用超算历史发展知识管理系统!\n");
	SqList L;
	creatList(&L);
	/*可用以下代码代替creat函数
	InitList(&L);
	printf("初始化成功!\n");
	printf("请输入三条超算发展历史:\n");
	for (int i = 0; i < 3; i++) {
		ElemType x;
		scanf("%s %s %d", &x.name, &x.people, &x.year);
		ListInsert(&L, x);
	}
	printf("输入成功!\n");
	*/
	PrintList(&L);
	printf("\n请选择你要执行的操作\n");
	printf("1 : 插入新数据\n");
	printf("2 : 删除数据\n");
	printf("3 : 根据超算名称查找\n");
	printf("4 : 查询某条记录\n");	
	printf("5 : 记录某条修改\n");

	int op;
	while (scanf("%d", &op) && op) {
		if (op == 1) {
			printf("请输入数据:\n");
			ElemType x;
    		scanf("%s %s %d", &x.name, &x.people, &x.year);
			if(ListInsert(&L, x))
				printf("插入成功!\n");
			PrintList(&L);
		}
		else if (op == 2) {
			printf("请输入想要删除第几条数据:");
			int j;
			scanf("%d",&j); 
			if(ListDelete(&L, j-1))
				printf("删除成功!\n");
			PrintList(&L);
		}
		else if (op == 3) {
			printf("请输入超算名称:\n");
			char name[20];
            scanf("%s", &name);
			if (locationList(&L, name) != 0)
				printf("该超算是第%d条记录!\n", locationList(&L,name));
			else
				printf("没有查询到这台超算!\n");
		}
		else if(op == 4){
			printf("请输入想要查询的位置:\n");
		    int num;
		    ElemType e;
			scanf("%d",&num);
			if(LocateElem(&L,num,&e) != 0)
        		printf("姓名 : %s 开发人员 : %s 年份 : %d\n", e.name, e.people, e.year);
			else
				printf("位置有误!\n");
		} 
		else if (op == 5) {
			printf("请输入需要修改第几条数据:\n");
			int local;
			scanf("%d",&local); 
			printf("请输入准备修改的数据:\n");
			ElemType x;
			scanf("%s %s %d", &x.name, &x.people, &x.year);
			if(ReviseElem(&L,local-1, x))
				printf("插入成功!\n");
			PrintList(&L);
		}
		else
				printf("查询失败!\n");
		
	}
}```

 

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 对于编写顺序表的初步初始化插入遍历三个基本操作函数,可以使用以下代码实现。 1. 初步初始化操作函数: def init_seq_list(seq_list, size): for i in range(size): seq_list.append(0) 其中,seq_list代表顺序表,size代表顺序表的大小。 2. 插入操作函数: def insert_seq_list(seq_list, pos, value): seq_list.insert(pos, value) 其中,seq_list代表顺序表,pos代表插入的位置,value代表插入的数值。 3. 遍历操作函数: def traverse_seq_list(seq_list): for i in range(len(seq_list)): print(seq_list[i]) 其中,seq_list代表顺序表。 以上三个操作函数都是顺序表基本操作函数,通过调用这些函数可以实现顺序表的各种操作,比如插入查找删除等。 ### 回答2: 顺序表是一种常用的数据结构,具有结构简单、存取方便、随机存储等特点。在使用顺序表时,我们需要编写一些基本的操作函数,如初始化插入遍历等。下面,我将详细介绍编写这三个基本操作函数的方法。 1. 初始化顺序表 初始化顺序表是指对顺序表进行一些必要的预处理,如初始化表长、分配存储空间等。初始化顺序表的函数一般形式如下: void InitList(SqList &L) { L.elem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType)); if(!L.elem) exit(ERROR); L.length = 0; L.listsize = LIST_INIT_SIZE; } 在初始化函数中,我们首先分配一块存储空间,即使用malloc函数动态分配一段内存空间,并将其首地址赋值给L.elem,如果分配不成功则退出。然后,我们将L.length赋值为0,表示表中元素个数为0;L.listsize赋值为LIST_INIT_SIZE,表示当前分配的存储空间大小为LIST_INIT_SIZE,LIST_INIT_SIZE一般是一个常量。至此,我们完成了顺序表初始化操作。 2. 插入元素顺序表插入元素是常见的操作,有时我们需要在表中间或头部插入元素,有时需要在表尾插入元素。不论在何处插入元素,我们需要确保插入元素顺序不变,并且当存储空间不足时,需要进行动态扩容。一个插入元素的函数一般形式如下: bool ListInsert(SqList &L, int i, ElemType e) { if(i < 1 || i > L.length + 1) return false; if(L.length >= L.listsize) { ElemType *newBase; newBase = (ElemType *)realloc(L.elem, (L.listsize + LISTINCREMENT) * sizeof(ElemType)); if(!newBase) exit(ERROR); L.elem = newBase; L.listsize += LISTINCREMENT; } ElemType *p, *q; q = &(L.elem[i-1]); for(p = &(L.elem[L.length-1]); p >= q; --p) *(p+1) = *p; *q = e; ++L.length; return true; } 在函数中,我们首先判断插入的位置是否合法,即i的值是否在合法范围内;当存储空间不足时,我们需要动态扩容,即调用realloc函数重新分配一块内存空间,将L.elem指向新分配的空间,同时更新L.listsize的值。接着,我们采用类似于冒泡排序的方式,将表中的元素逐个向后移动一位,为插入元素腾出位置。最后,将待插入元素e放入q指向的位置,并将L.length的值加1,表示表中元素个数增加了1。 3. 遍历顺序表 遍历顺序表是指对表中所有元素依次执行某些操作,如输出表中所有元素或对元素进行处理等。遍历顺序表的函数可用于统计各类元素的个数、查找符合条件的元素等。一个遍历顺序表的函数一般形式如下: void ListTraverse(SqList L) { ElemType *p = L.elem; for(int i = 1; i <= L.length; ++i) { printf("%d ", *p); ++p; } printf("\n"); } 在函数中,我们首先定义一个指向L.elem的指针p,并设置初始值为L.elem,随后采用for循环的方式依次遍历表中所有元素,将每个元素的值输出,并将指针p向后移动一位。最后,我们在末尾输出一个换行符。\end{document} ### 回答3: 顺序表数据结构中最基础的线性结构,其基本操作包括初始化插入遍历。本文将介绍如何编写顺序表的三个基本操作函数。 1. 初始化函数 初始化函数是顺序表最基本的操作函数,其作用是初始化并建立一个空的顺序表,常用于顺序表的创建和重置。 初始化函数通常包括以下步骤: (1)动态申请容量为maxsize的存储空间。 (2)判断是否申请成功,若失败则返回错误信息。 (3)将顺序表的当前长度置为0,表示当前顺序表为空。 (4)将顺序表的最大容量maxsize赋值给顺序表表头。 以下是顺序表初始化函数的代码实现: #define MAXSIZE 100 //顺序表最大容量 typedef struct{ DataType data[MAXSIZE]; //顺序表存储数据元素的数组 int length; //顺序表当前长度 int maxsize; //顺序表最大容量 }SeqList; //顺序表类型定义 SeqList* InitList(){ SeqList* L=(SeqList*)malloc(sizeof(SeqList)); //动态申请存储空间 if(!L){ printf("Memory allocation failed.\n"); exit(0); //退出程序 } L->length=0; L->maxsize=MAXSIZE; //将最大容量赋值给表头 return L; } 2. 插入函数 顺序表插入操作是向表中插入一个元素,使得该元素成为指定位置后面的元素插入函数的常用形式包括插入到表头、插入到表尾和插入到指定位置。 插入函数常用的步骤如下: (1)判断插入位置pos是否合法,即pos>=1&&pos<= length+1,其中length表示当前顺序表长度。 (2)若pos>length,则新插入元素在表尾。否则需将插入位置之后的元素依次往后移动一位,为新元素腾出插入位置。 (3)将新的元素插入到合适的位置。 (4)将顺序表的当前长度增加1。 以下是向顺序表插入一个元素的代码实现: bool InsertList(SeqList* L,int pos,DataType x){ if(pos<1||pos>L->length+1){ //插入位置不合法 return false; } if(L->length>=L->maxsize){ //存储空间已满,无法插入元素 return false; } for(int i=L->length;i>=pos;i--){ //将插入位置之后的元素依次往后移动一位 L->data[i+1]=L->data[i]; } L->data[pos]=x; //新元素插入到合适的位置 L->length++; //顺序表长度增加1 return true; } 3. 遍历函数 顺序表遍历操作是按照元素顺序依次访问每个元素,并对其进行某些操作,如输出、修改删除等。遍历函数常用的方式包括顺序遍历和倒序遍历顺序遍历顺序表的实现方法很简单,只需要使用for循环按顺序访问每一个元素即可。 倒序遍历顺序表则需要使用while循环,并从末尾元素开始依次向前访问顺序表中的所有元素。 以下是顺序遍历顺序表的代码实现: void PrintList(SeqList* L){ for(int i=1;i<=L->length;i++){ printf("%d ",L->data[i]); } printf("\n"); } 以上就是顺序表初始化插入遍历三个基本操作函数的代码实现。需要注意的是,在实现每个操作函数时,都要考虑到可能出现的异常情况,如内存不足、插入位置不合法、存储空间已满等情况,并返回相应的错误信息。在使用顺序表时,也要注意合理地控制顺序表的大小,避免浪费过多存储空间或造成空间不足的情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值