第二章 向量、栈和队列(一)——线性表

本文介绍了线性表的抽象模型和数据结构表示,包括线性表的基本操作。在C语言实现中,讨论了C99标准的布尔类型以及在函数中出现的编译警告,如指针/整数类型不匹配和返回类型的转换警告,并邀请读者在评论区分享解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线性表

线性表的抽象模型

  • 线性表:n 个数据元素组成的一个有限序列 k0, k1 , … , kn-1
元素性质
k0开始结点,没有前趋,仅有一个后继
kn-1终端结点,没有后继,仅有一个前趋
ki ( i 在(0,n-1)区间内) 有且仅有一个前趋ki-1和一个后继ki+1
n线性表的长度,当n=0时,线性表为空表
  • 线性表的分类:
类别 定义
向量数据类型相同的数据元素组成的线性表。
例:串是由单个字符组成的线性表,也可称为字符向量。
文件 记录:数据元素为组合项时,组合项中的数据项可以为不同的数据类型。
由记录组成的线性表称为文件。
  • 线性表的基本操作:
操作解释
表的初始化生成一个空表
判断表是否为空表结点的个数是否为0
判断表是否已满表结点的个数是否为允许的最大数
求表长表中结点的个数
取表中第 i 个元素取给定地址 i 的元素
查找表中值为 x 的结点返回所有值为 x 的结点的地址
插入结点在表中第 i 个位置上插入结点
删除结点删除表中第 i 个位置的结点
  • 线性表的抽象数据模型:
ADT LinearList
{
	Data
		数据元素有限序列 k0, k1,...,kn-1
		k0无前趋,后继为k1
		kn-1无后继,前趋为kn-2
		ki前趋为ki-1,后继为ki+1,0<i<n-1
	Operations
		InitList
			Input:				申请表的空间长度	
			Preconditions:		无
			Process:			申请一个表空间,生成一个空表
			Output:				表空间位置和范围,表长为0
			Postconditions:		表已存在										
		DestroyList
			Input:				无
			Preconditions:		表已存在
			Process:			撤销一个表
			Output:				无
			Postconditions:		表不存在
		ListEmpty
			Input:				无
			Preconditions:		表已存在
			Process:			判断表是否为已满
			Output:				若为空表返回TRUE,否则返回FALSE
			Postconditions:		无
		ListFull
			Input:				无
			Preconditions:		表已存在
			Process:			判断表是否为空表
			Output:				若表已满,返回TRUE,否则返回FALSE
			Postconditions:		无
		ListLength
			Input:				无
			Preconditions:		表已存在
			Process:			求表的结点个数
			Output:				返回表的长度
			Postconditions:		无
		GetElem
			Input:				结点序号 i 
			Preconditions:		表已存在
			Process:			按 i 读取 ki
			Output:				若读取成功,返回 ki 的值,否则返回NULL
			Postconditions:		无
		LocateElem
			Input:				要在表中查找到值
			Preconditions:		表已存在
			Process:			扫描表,找与查找值相等的结点
			Output:				若查找成功,则返回找到的结点的序号,否则返回-1
			Postconditions:	
		InsertElem
			Input:				新结点要插入的位置
			Preconditions:		表已存在
			Process:			将新结点按插入位置插入其中
			Output:				若插入成功,则返回TRUE,否则返回FALSE
			Postconditions:	表中增加一个结点,表的长度加一
		DeleteElem
			Input:				要删除结点的序号				
			Preconditions:		表已存在
			Process:			删除指定序号的结点
			Output:				若删除成功,则返回TRUE,否则返回FALSE
			Postconditions:		表中减少一个结点,表的长度减1	
}

线性表的数据结构表示

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int ElementType;

typedef struct linearList{
    ElementType * data;
    int MaxSize;
    int Last;
}LinearList;

/* 线性表的初始化 */
void InitList(LinearList * L,int size){
    if(size>0){
        L->MaxSize = size;
        L->Last = 0;
        L->data = (ElementType *)malloc(sizeof(ElementType) * L ->MaxSize);
    }
}

/* 释放线性表的空间 */
void FreeList(LinearList *L){
    free(L->data);
}

/* 判断线性表是否为空 */
bool ListEmpty(LinearList *L){
    return (L->Last <=0) ? true : false;
}

/* 判断线性表是否为满 */
bool ListFull(LinearList *L){
    return (L->Last >= L->MaxSize) ? true : false;
}

/* 求线性表的长度 */
int ListLength(LinearList *L){
    return L->Last;
}
/* 取线性表的第 i 个表目 */
ElementType getElement(LinearList *L, int i){
    return (i>0 ||i<L->Last) ? L->data[i] : NULL;

}

/*
    在线性表中查找值为 x 的结点
    若查找成功,返回结点的序号,否则返回-1
    若表中符合条件的结点有多个,返回最前面的结点的序号
*/
int LocalElem(LinearList *L, ElementType x){
    int i;
    for(i=0;i<L->Last;i++){
        if(L->data[i] == x) return i;
    }
    return -1;
}

/*
    在线性表中的第 i 个位置插入值为 x 的结点
    插入成功返回TRUE,否则返回FALSE
*/
bool InsertElem(LinearList *L,ElementType x, int i){
    int j;
    if(i<0 || i>L->Last || L->Last == L->MaxSize){
        return false;
    }else{
        for(j=L->Last-1;j>=i;j--)
            L->data[j+1] = L->data[j];
        L->data[i] = x;
        L->Last++;
        return true;
    }
}

/*
    删除表中第 i 个结点
    删除成功返回TRUE,否则返回FALSE
*/
bool DeleteElem(LinearList *L, int i){
    int j;
    if(i<0 || i>=L->Last || L->Last==0) return false;
    else{
        for(j=i;j<L->Last-1;j++){
            L->data[j]=L->data[j+1];
        }
        L->Last--;
        return true;
    }
}

/* 打印线性表的表目 */
void printout(LinearList *L){
    int i;
    for(i=0;i<L->Last;i++){
        printf("%d ",L->data[i]);
    }
    printf("\n");
}

首先这个代码里面是有一些问题的:
(1)如果你使用的是C语言实现的代码,从C99标准开始,C语言有布尔类型了,关键字是“_Bool”,其取值只能是0和1。如果你使用的编译器版本支持C99标准,就可以直接使用布尔类型数据。
一些具体的使用方法请参考:
链接: C语言的布尔类型(_Bool).
(2)在这个函数中的编译是会出现两个警告的。

/* 取线性表的第 i 个表目 */
ElementType getElement(LinearList *L, int i){
    return (i>0 ||i<L->Last) ? L->data[i] : NULL;

}

||== Build: Debug in LinearList (compiler: GNU GCC Compiler) ==
D:\C++\DataStructure\LinearList\main.c||In function ‘getElement’:
D:\C++\DataStructure\LinearList\main.c|42|warning: pointer/integer type mismatch in conditional expression
D:\C++\DataStructure\LinearList\main.c|42|warning: returning ‘void *’ from a function with return type ‘ElementType’ {aka ‘int’} makes integer from pointer without a cast [-Wint-conversion]
||== Build finished: 0 error(s), 2 warning(s) (0 minute(s), 0 second(s)) ==|

  • warning: pointer/integer type mismatch in conditional expression
    条件表达式中整数\指针数据类型不匹配,放到这个代码中来说,我用的是ElementType作为函数返回值的类型,但是我的条件表达式中出现了NULL。因为我ElementType是int,这个NULL和我的ElementType不能匹配,所以就出现了这样的报错。
  • warning: returning ‘void *’ from a function with return type ‘ElementType’ {aka ‘int’} makes integer from pointer without a cast [-Wint-conversion]
    警告:从返回类型为 ‘ElementType’ {aka ‘int’} 的函数返回 'void *'从指针生成整数而不进行强制转换 [-Wint-conversion]
    这个警告其实感觉上是上一个警告的延伸,int不能强制转换为string类型的数据,也就是ElementType不能和Null进行匹配

(目前没有想到合适的解决办法,如果小伙伴们有什么好的解决办法,欢迎在评论区和我交流)

【测试】

int main()
{
    LinearList *L = (LinearList *)malloc(sizeof(LinearList));
    
    InitList(L,5);
    InsertElem(L,10,0);
    InsertElem(L,20,0);
    InsertElem(L,30,0);
    InsertElem(L,40,0);
    InsertElem(L,50,0);
    
    if(InsertElem(L,60,0))
        printout(L);
    else if(ListFull(L))
        printf("List is full, failed to insert\n");
    printout(L);
    
    DeleteElem(L,1);
    DeleteElem(L,1);
    printf("After twice deletions the list is ");
    printout(L);
    
    printf("The location of data 20 is %d\n",LocalElem(L,20));
    printf("The 3rd value is %d\n",getElement(L,2));
    FreeList(L);
    
    return 0;
}

List is full, failed to insert
50 40 30 20 10
After twice deletions the list is 50 20 10
The location of data 20 is 1
The 3rd value is 10
Process returned 0 (0x0) execution time : 0.058 s
Press any key to continue.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值