C语言强化-2.线性表&代码

与408的关联:1. 顺序表结合排序出了很多大题。2. 链表本身出很多大题!

顺序表的顺序表示原理

  1. 线性表的特点:
    1. 表中元素的个数是有限
    2. 表中元素的数据类型都相同。意味着每一个元素都占用相同大小的空间。
    3. 表中元素具有逻辑上的顺序性,在序列中各元素排序有其先后顺序。
  2. 线性表第一个元素的数组下标是0

线性表的顺序表示(顺序表)

顺序表的定义

#define MaxSize 50  //定义线性表的长度
typedef struct{    
	ElemType data[MaxSize];  //顺序表的元素
	int len;    //顺序表的当前长度
}SqList;    顺序表的类型定义

优点:

  1. 可以随机存取(根据表头元素地址和元素序号)表中任意一个元素。
  2. 存储密度高,每个结点只存储数据元素。

缺点:

  1. 插入和删除操作需要移动大量元素。
  2. 线性表变化较大时,难以确定存储空间的容量。
  3. 存储分配需要一整段连续的存储空间,不够灵活。 

插入操作

  • 最好情况:新元素插入到表尾,不需要移动元素,最好时间复杂度 = O(1)
  • 最坏情况:新元素插入到表头,需要将原有的n个元素全都向后移动,最坏时间复杂度 = O(n)
  • 平均情况:假设新元素插入到任何一个位置的概率相同,平均移动元素的次数是n/2,时间复杂度 = O(n)
//判断插入位置i是都合法(满足i <= length + 1)
//判断存储空间是否已满(即插入e后是否会超出数组长度)
for(int j = L.length;j >= i;j--)  //将第i个元素及之后的元素后移
				L.data[j] = L.data[j - 1];
		L.data[i =-1] = e;  //在位置i处放入e
		L.length++;  //长度加1

删除操作

  • 最好情况:删除表尾元素,不需要移动元素,最好时间复杂度 = O(1)
  • 最坏情况:删除表头元素,需要将后续的n - 1个元素全都向前移动,最坏时间复杂度 = O(n)
  • 平均情况:假设删除任何一个元素的概率相同,平均移动元素的次数为(n-1)/2,时间复杂度 = O(n)
e = L.data[i - 1];  //将被删除的元素赋值给e
for(int j = i;j < L.length;j++)  //将第i个元素后哦的元素前移
		L.data[j - 1] = L.data[j];  //注意位序、数组下标的关系,并从前面的元素依次移动
L.length--;  //长度减1

动态分配

#define InitSize 10  //顺序表的初始长度
typedef struct{
		ElemType * data;  //指示动态分配数组的指针
		int MaxSize;  //顺序表的最大容量
		int length;  //顺序表的当前长度
}SeqList;  //顺序表的类型定义(动态分配方式)
//C的初始动态分配语句
L.data = (ElemType*)malloc(sizeof(ElemType)*InitSize);
//C++的初始动态分配语句
L.data = new ElemType[InitSize];

顺序表的初始化及插入操作实践

#include <stdio.h>

#define MaxSize 50
typedef int ElemType;//让顺序表存储其他类型元素时可以快速完成代码修改
typedef struct {
    ElemType data[MaxSize];
    int length;
}SqList;
//顺序表的插入,因为L会改变,因此这里要用引用
bool ListInsert(SqList &L,int i,ElemType element){
    //判断i(插入的位置)是否合法
    if(i < 1 || i > L.length + 1){
        return false;
    }//如果存储空间满了,不能插入
    if(L.length == MaxSize){
        return false;//未插入返回false
    }
    //把后面的元素依次往后移,空出位置,放入插入的元素
    for(int j = L.length;j >= i;j--){
        L.data[j] = L.data[j - 1];
    }
    L.data[i - 1] = element;//放入要插入的元素
    L.length++;//顺序表长度要+1
    return true;//插入成功返回true
}

//打印顺序表
void PrintList(SqList L){
    int i;
    for(i = 0;i < L.length;i++){
        printf("%3d",L.data[i]);
    }
    printf("\n");
}

//顺序表的初始化及插入
int main() {
    SqList L;//顺序表的名称
    bool ret;//ret用来装函数的返回值
    L.data[0]=1;
    L.data[1]=2;
    L.data[2]=3;
    L.length = 3;
    ret = ListInsert(L,2,60);
    if(ret){
        printf("insert sqlist success\n");
        PrintList(L);
    }else{
        printf("insert sqlist failed\n");
    }
    return 0;
}
//输出
insert sqlist success
  1 60  2  3

顺序表的删除及查询实践

//删除顺序表中的元素,i是要删除的元素的位置,e是为了获取被删除的元素的值
bool ListDelete(SqList &L,int i,ElemType &e){
    //判断删除的元素的位置是否合法
    if(i < 1 || i > L.length){
        return false;
    }
    e = L.data[i -1];//首先保存要删除元素的值
    int j;
    for(j = i - 1;j < L.length-1;j++){//往前移动元素
        L.data[j] = L.data[j + 1];
    }
    L.length--;//顺序表长度-1
    return true;
}
//查找某个元素的位置,找到就返回对应的位置,没找到就返回0
int LocateElem(SqList L,ElemType element){
    int i;
    for(i = 0;i < L.length;i++){
        if(element == L.data[i]){
            return i+1;//因为i是数组的下标,i+1以后才是顺序表的下标
        }
    }
    return 0;//循环结束没找到
}
int main() {
    SqList L;//顺序表的名称
    bool ret;//ret用来装函数的返回值
    L.data[0]=1;
    L.data[1]=2;
    L.data[2]=3;
    L.length = 3;
    ElemType del;//删除的元素存入del中
    ret = ListDelete(L,1,del);
    if(ret){
        printf("delete sqlist success\n");
        printf("delete element = %d\n",del);
        PrintList(L);
    }else{
        printf("delete sqlist failed\n");
    }
    printf("-----------------\n");
    int pos;//存储元素位置
    pos = LocateElem(L,60);
    if(pos){
        printf("find this element\n");
        printf(" element pos = %d\n",pos);
    }else{
        printf("don't fint this element\n");
    }
    return 0;
}
//输出
delete sqlist success
delete element = 1
 60  2  3
-----------------
find this element
 element pos = 1

线性表的链式存储

线性表的链式表示(链表)

单链表

typedef struct LNode{  //定义单链表结点类型
		ElemType data;  //每个结点存放一个数据元素
		struct LNode *next;  //指针指向下一个结点
}LNode, *LinkList;

若链表有头结点,则头指针永远指向头结点,不论链表是否为空,头指针均不为空。头指针是链表的必需元素,它标识一个链表。

  1. 头指针:链表中第一个结点的存储位置,用来标识单链表。
  2. 头结点:在单链表第一个结点之前附加一个结点,为了操作上方便。

//初始化一个单链表(带头结点)
bool InitList(LinkList &L){
		L = (LNode *) malloc(sizeif(LNode));  //分配一个头节点
		if (L == NULL)  //内存不足,分配失败
				return false;
		L -> next = NULL;  //头节点之后暂时还没有结点
		return true;
}

优点:

  1. 插入和删除操作不需要移动元素,只需要修改指针。
  2. 不需要大量的连续存储空间。

缺点:

  1. 单链表附加指针域,也存在浪费存储空间的缺点。
  2. 查找操作时需要从表头开始遍历,依次查找,不能随机存取。

插入
//创建新结点
q = (LNode*)malloc(sizeof(LNode))
q -> data = x;
//表头/中间插入元素
q -> next = p -> next;
p -> next = q;
//表尾插入元素
p -> next = q;
q -> next = NULL;
删除
//表头、中间、表尾删除操作
p = GetElem(L,i - 1);//查找删除位置的前驱结点
q = p -> next;
p -> next = q -> next;
free(q);
查找
//按序号查找节点值
LNode *p = L -> next;
int j = 1;
while(p && j < i){
		p = p -> next;
		j++;
}
return p;
//按值查找节点
LNode *p = L -> next;
while(p != NULL && p -> data != e){
		p = p -> next;
}
return p;
  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 创建线性表的步骤如下: 1. 定义线性表的数据类型,包括元素类型和线性表的结构体类型。 2. 申请线性表所需的内存空间,可以使用malloc函数动态分配内存。 3. 初始化线性表,包括设置线性表的长度、容量和元素值等。 4. 在线性表中插入元素,可以在表头或表尾插入,也可以在指定位置插入。 5. 在线性表中删除元素,可以删除表头或表尾元素,也可以删除指定位置的元素。 6. 在线性表中查找元素,可以按照元素值或元素位置进行查找。 7. 修改线性表中的元素值,可以按照元素位置进行修改。 8. 释放线性表所占用的内存空间,可以使用free函数释放内存。 以上就是创建线性表的基本步骤,需要根据具体情况进行调整和完善。 ### 回答2: 线性表是数据结构中常用的一种形式,它是由n个元素组成的有限序列,每个元素都有唯一的前驱和后继。顺序表就是一种线性表的存储方式,它的元素在内存中是连续存储的。 创建顺序表的过程主要涉及两个方面:确定表的结构和初始化表的内容。首先,我们要确定顺序表的容量,也就是它最多能够存放多少个元素,这个容量一旦确定,就不能再改变。因此,我们在创建顺序表时需要定义一个常量MAXSIZE,用来表示顺序表的容量。 接着,我们需要定义一个结构体来表示顺序表,这个结构体包括两个成员:一个指向存储元素的数组的指针和一个表示顺序表的当前长度的整数。在定义结构体时,我们需要使用MAXSIZE常量来定义数组的长度,这样才能保证数组不会越界。 定义结构体之后,我们就可以开始初始化顺序表的内容了。初始化顺序表就是向数组中依次插入元素的过程。插入元素的方式有两种:一种是在表的尾部插入元素,另一种是在表的指定位置插入元素。 在尾部插入元素的方式比较简单,只需要将元素赋值给数组的最后一个位置即可。在指定位置插入元素稍微麻烦一些,需要将指定位置之后的元素全部向后移动一个位置,然后再将新元素插入到指定位置。 在创建顺序表时,我们还需要考虑如何释放表的空间。当顺序表不再使用时,应该将占用的内存空间释放掉,否则就会造成内存泄露。释放顺序表的空间很简单,只需要使用C语言中的free()函数即可。 总之,创建顺序表的过程需要注意确定表的结构、初始化表的内容和释放表的空间这几个方面,只有这些方面都注意到了,才能够创建出一个完整可用的顺序表。 ### 回答3: 创建线性表,即在内存中分配一段连续的存储空间,存储线性表的元素。创建线性表的前提是确定线性表的元素类型和容量。元素类型可以是任何数据类型,容量则是线性表的最大元素个数。 顺序表是一种线性表的实现方式,创建顺序表需要确定顺序表的容量和元素类型,然后在内存中动态分配一段相应大小的连续存储空间。顺序表中存储的元素是按照顺序排列的。 创建顺序表的过程中需要考虑以下几个步骤: 1.确定元素类型和容量。根据实际需求,确定顺序表中存储元素的数据类型和最大容量。 2.在内存中分配存储空间。根据顺序表容量的大小,在内存中分配相应大小的连续存储空间。顺序表中元素的存储位置是连续的,因此需要一次性分配足够的存储空间,避免后续扩容操作。 3.初始化顺序表。初始化顺序表中元素的值,可以根据实际需求设置默认值或读取用户输入的值进行初始化。 4.返回顺序表引用。返回指向顺序表的指针或引用,方便后续操作。 顺序表的创建是线性表实现的基础,正确的创建顺序表可以提高线性表的使用效率和可靠性。在实际开发中,顺序表的创建通常由函数或类实现,方便用户使用和维护。因此,在创建顺序表时也需要考虑函数或类的设计和实现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Annabelle.02

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值