顺序表基本操作<小白一听就懂!!!><超详细>&&<接地气>

  • ***小编前言***
  • 完整代码
  • // 头文件
  • //主函数
  • // 初始化
    • /*运用指针*/
    • /*空类型*/
    • /*理解函数-独家秘笈*/
  • // 增加元素
    • /*i++与++i*/
  • // 打印顺序表
    • /*遍历数组循环条件的两种表达*/
  • // 按序号查找
    • /*数组序号与下标关系*/
  • // 按照数值查找
  • // 插入
    • /*后移操作*/
  • // 删除
    • /*无需判满*/
    • /*前移*/。
  • // 逆置
  • // 打印顺序表长度
  • //----------------------------------------帅哥美女都点这里----------------------------------------

小编前言

主打一个浅显易懂 计科新生角度,分享对顺序表的理解,贴合初学者的思路分析讲解。
trust yourself,跟着小编的节奏,盘他!
闲言少叙,话不多少,发车!

完整代码

附详细注释

//顺序表中基本操作的实现,并会在主函数中调用这些基本操作:
//(1)创建顺序表,添加至少8个元素,并输出;
//(2)查找第5个元素值;
//(3)查找顺序表中是否存在99,若存在找出其位置;
//(4)在第5个位置插入100;
//(5)删除第4个位置的元素;
//(6)将顺序表中的元素逆置。#include<stdio.h>
#define Maxlength 100
//定义结构体
typedef struct
{int data[Maxlength];int length;
}List;
void InitList(List* L);//初始化
void AddList(List* L);//增加元素
void PrintList(List L);//输出顺序表
int LocatSearch(List L, int i);//按序号查找
int DateSearch(List L, int e);//按照数值查找
void InserchList(List* L, int i, int e);//插入
void DeleteList(List* L, int i);//删除
void InverList(List* L, int Maxsize);//逆置
int LengthList(List L);//打印顺序表长度#include"Head.h"
int main()
{int x;//存储按序号查找的返回值(返回的是数据的值)int i;//存储按照数值查找的返回值(返回的是数据的序号)int n;//储存线性表长度 bList L;InitList(&L);AddList(&L);PrintList(L);//按序号查找x= LocatSearch(L, 5);if (x != -1){printf("\n第五个元素的值为:%d\n",x);}//按数值查找i = DateSearch(L, 99);if (i)printf("99在第%d个位置\n", i);elseprintf("99不存在\n");printf("\n在第5个位置插入100后为:\n");InserchList(&L, 5, 100);PrintList(L);DeleteList(&L, 4);n=LengthList(L);//确定顺序表的长度InverList(&L, n);//进行逆置操作printf("顺序表逆置之后为:\n");PrintList(L);
}
//初始化
void InitList(List *L)
{L->length = 0;return;
}
//增加元素
void AddList(List* L)
{int x;char select;do{  //即使开始初始化了但是仍然要判满,输入因为是一个循环if (L->length == Maxlength){printf("Fuck!顺序表已满!");return;}printf("请输入要增加元素的值:");scanf_s("%d", &x);L->data[L->length++] = x;printf("是否继续添加?(Y/N)");scanf_s(" %c", &select);//加空格防止回车误触} while (select == 'y' || select=='Y');//逻辑或运算两边||都要有字符,不可一边有一边没有
}
//打印数据函数
void PrintList(List L)
{int i;for (i = 0; i <= L.length - 1; i++){printf("(%d)%d\t", i + 1, L.data[i]);}printf("\n");
}
//按序号查找
int LocatSearch(List L, int i)
{ //判断输入序号是否合法if (i<1 || i>L.length){printf("您输入的数据非法!\n");return -1;}return L.data[i-1];//因为i是传入元素的序号,下标=序号-1
}
//按照数值查找
int DateSearch(List L, int e)
{int i;for (i = 0; i < L.length; i++)//遍历所有数组元素{if (L.data[i] == e){return i + 1;}}return 0;
}//插入元素
void InserchList(List* L, int i, int e)
{int j;//插入之前首先判满if (L->length == Maxlength)//注:=为赋值符号;而数学等号为=={printf("fuck!顺序表已满!\n");return;}//判断插入位置是否合法if (i<1 || i>L->length + 1)//length + 1因为可以在表的末尾加,也即是最后一个序号为length的元素后面{printf("插入位置错误!\n");return;}//插入位置之后的所有元素都要向后移动一个位置for (j = L->length - 1; j >= i - 1; j--)//j = l->length - 1将j初始化为顺序表中最后一个元素的下标{                                     //循环条件j >= i - 1保证了只有从待插入位置开始之后的所有元素才需要被移动L->data[j + 1] = L->data[j];//后移  //循环语句j--将j逐渐减小,}L->data[i - 1] = e;//插入eL->length++;//表的长度加一return;
}//删除
void DeleteList(List* L, int i)
{//不用判空,因为在判断位置是否合法的时候就已经判断了是否是空的 //判断删除位置是否合法if (i<1 || i>L->length + 1){printf("插入位置错误!\n");return;}int j;for (j = i; j < L->length; j++){L->data[j - 1] = L->data[j];//前移}L->length--;//长度-1return;
}
//逆置
//在循环体中,temp变量用于暂存顺序表中第i个元素的值,
//然后将第i个元素和对应的最后一个元素进行交换
//即将第i个元素的值赋给l->data[Maxsize - 1 - i]
//Maxsize-1-i位置上的元素赋值为temp
void InverList(List* L, int Maxsize)//Maxsize为最大元素的序号
{int i;int temp;for (i = 0; i < Maxsize / 2;i++){temp = L->data[i];L->data[i] = L->data[Maxsize - 1 - i];//Maxsize-1,为数组的下标,数组下标首尾进行交换L->data[Maxsize - 1 - i] = temp;}return;
}
//输出顺序表长度
int LengthList(List L)
{return L.length;
}

// 头文件

#include<stdio.h>
#define Maxlength 100  //  定义用于存储顺序表的数组
//  定义结构体
typedef struct
{int data[Maxlength];int length;  //  标示顺序表的最大长度
}List;  //  给typedef struct起一个“小名儿”叫Listvoid InitList(List* L);  //  初始化
void AddList(List* L);  //  增加元素
void PrintList(List L);  //  输出顺序表
int DateSearch(List L, int e);  //  按序号查找
int LocatSearch(List L, int i);  //  按照数值查找
void InserchList(List* L, int i, int e);  //  插入
void DeleteList(List* L, int i);  //  删除
void InverList(List* L, int Maxsize);  //  逆置
int LengthList(List L);  //  打印顺序表长度

//主函数

int main()
{int x;  //  存储按序号查找的返回值(返回的是数据的值)int i;  //  存储按照数值查找的返回值(返回的是数据的序号)int n;  //  储存线性表长度 bList L;  //  申请一个用结构体自定义类型的空间InitList(&L);AddList(&L);PrintList(L);//  按序号查找x= DateSearch(L, 5);if (x != -1){printf("\n第五个元素的值为:%d\n",x);}//  按数值查找i = LocatSearch(L, 99);if (i)printf("99在第%d个位置\n", i);elseprintf("99不存在\n");//  插入printf("\n在第5个位置插入100后为:\n");InserchList(&L, 5, 100);PrintList(L);DeleteList(&L, 4);n=LengthList(L);  //  确定顺序表的长度InverList(&L, n);  //  进行逆置操作printf("顺序表逆置之后为:\n");PrintList(L);
}

// 初始化

void InitList(List *L)
{L->length = 0;  //  初始化,即令顺序表为空,也就是使表长为0return;
}
初始化目的

内存中为顺序表申请的这块空间,之前可能被使用过,因此其中存在一些残留的垃圾数值,初始化可对垃圾值进行清除,避免在操作时访问到未被初始化的元素导致程序崩溃。

核心思想:函数返回值类型为空,运用指针,通过形参表回传参数(L的length)

/运用指针/

那么问题来了:为什么要用指针?直接对length进行修改(L.length=0)不行嘛?

想要弄清楚这,还要从你学的清晰的一塌糊涂的C语言谈起:

C 语言中自定义函数的参数传递方式有两种:单向传递双向传递。其中,单向传递是指:将参数的值从调用函数(可理解为main函数)传递给被调用函数(自定义函数),而不会将被调用函数中变量值传递回调用函数。
简而言之,就是在自定义函数中,对主函数参数变量所做的修改是无效的。
这点小编是从两个方面去理解的:
1.函数内部变量独立:被调用函数中的变量和调用函数中的变量是独立的,它们有不同的内存地址和空间。即使变量名相同,它们也不是同一个变量,而是两个互相独立的变量。在被调用函数中,函数参数是局部变量,它会在函数执行结束后被自动销毁。因此,在被调用函数中不能使用参数的地址或引用,否则将会访问到无效的内存地址,引发程序错误。
2.只传递参数值:在单向传递中,只传递了参数的值,而没有传递参数的地址或引用。因此,在被调用函数中修改参数的值并不会影响调用函数中的参数值。

显而易见,直接对修改length的值(L.length=0)是错误的

初始化要对顺序表中元素(也就是主函数中的元素)进行修改,故要用指针改变L.length的地址,再通过形参表回传。

/空类型/

函数中不需要返回任何数值给主函数。
说到函数返回值的类型,我们不得不再复习一下清晰的一塌糊涂的C:

/理解函数-独家秘笈/

《独家干货秘笈理解》
关于黑盒模型:
黑盒顾名思义:它是一个不可视的容器。C语言的函数可看做是一个黑盒,它隐藏了函数内部的具体实现,只关注函数输入和输出的关系:输入参数作为黑盒的输入,函数的执行过程是黑盒内部的处理过程,输出结果作为黑盒的输出。

接地气一点,小编将函数看做一个方程式,(emm可能有点不严谨)向形参表中传参,执行函数体,返回值,==给方程中设的未知数赋值,带入方程,得出结果

int main()
{int a = 0;int b = 1;int c = 2;  //  (给方程未知数x,y赋值a,b也就是1,2)a = fun(b,c);  //  传入参数(带入赋值后的未知数)printf("%d", a);return 0;
}
int fun(int x, int y)  //  执行函数体(将未知数带入方程)
{int z;z = x - y;return z;  //  输出返回值(得出结果)
}

无论方程(函数)多么复杂,都是同样的解题步骤(运行方式)。

这样一来函数的嵌套也就很好解释了:无非就是将方程中的一个未知数看成一个式子

int fun(int x, int y)  //  传入参数(执行函数体)带入方程
{int z;z = x - y;  //  嵌套Max函数z = Max(x, z);  //  fun函数中的参数x为Max函数的值(原方程未知数z看成另一个方程式)return z;  //  输出返回值(得出结果)
}
int Max(int x, int y)
{return x > y ? x : y;
}
回归正题,顺序表

// 增加元素

void AddList(List* L)
{int x;char ch;do{  //  即使开始初始化了但是仍然要判满,输入因为不仅仅输入这一次而是要循环起来if (L->length == Maxlength)  //  若表长等于数组最大长度{printf("Fuck!顺序表已满!");  //  则顺序表已满return;}printf("请输入要增加元素的值:");scanf_s("%d", &x);L->data[L->length++] = x;  //  将接收的数据存入顺序表(数组),每存一个数表长+1(length++)printf("是否继续添加?(Y/N)");scanf_s(" %c", &select);  //  加空格防止程序将回车误读,而发生错误} while (ch == 'y' || ch=='Y');  //  逻辑或运算两边||都要有字符,不可一边有一边没有
}
核心思想:1.插入操作要对顺序表进行修改,因此用指针类型,在形参表中回传参数2.插入前首先判满3.接收添加的元素并存入数组4.接收循环判断字符5.最外层用while循环套上,让其循环起来

/i++与++i/

i++是先用i进行运算,再进行+1操作
++1是先对i进行+1操作,再进行运算

// 打印顺序表

void PrintList(List L)
{int i;for (i = 0; i <= L.length - 1; i++)  //  for循环遍历数组{printf("(%d)%d\t", i + 1, L.data[i]);}printf("\n");
}
核心思想:顺序表存于数组内,输出顺序表即输出数组元素(用for循环遍历)注:打印仅仅是输出顺序表中内容,并不对表进行修改,可不用指针类型(当然用也无妨)

c语言一个函数只能返回一个返回值,so不要尝试用返回值打印 (小编开始是这么想的)

/遍历数组循环条件的两种表达/

i <= L.length - 1;
i < L.length;
二者都是将i遍历到数组的最大下标

// 按序号查找

//按序号查找
int DateSearch(List L, int e)
{ //判断输入序号是否合法if (i<1 || i>L.length)  //  i为序号,合法范围在1-length之间{printf("您输入的数据非法!\n");return -1;}return L.data[i-1];//因为i是传入元素的序号,下标=序号-1
}
核心思想:1.按照序号查找,返回的是元素的值,函数返回值类型为数组中数据元素的类型2.首先判断输入的序号是否合法3.若输入的元素经过检测,则返回数组元素下标为[i-1]位置的值(i为序号,数组是从下标为0的位置存的第一个元素)4.若未经过检测,则返回一个顺序表中不可能出现的数(例如-1),用于主函数书否输出返回值的判断条件

/数组序号与下标关系/

小编将其分为两种类型:
下标为0的位置开始存 数据:初学常用,基础且易理解的一种方式。数组下标=元素序号-1,如此也导致了,操作时的不便。
下标为1的位置开始存 数据:将data[0]的位置空出来,这种思想,在数据结构查找和排序章节涉及。data[0]空位:可设置监视哨,可用作为临时变量(temp),辅助数据的交换,同时使元素序号和数组下标一致。

// 按照数值查找

int LocatSearch(List L, int i)
{int i;for (i = 0; i < L.length; i++)//遍历所有数组元素{if (L.data[i] == e){return i + 1;}}return 0;
}
核心思想:1.按数值查找,返回的是元素的序号,返回值类型为整型2.(此处使用最基础的线性查找方式),从一端开始逐个比较查找,直到找到目标数据或查找到整个数据集为止,时间复杂度为O(n)。

注:还可使用其他查找方法(数据结构后半部分会讲到)

// 插入

//插入元素
void InserchList(List* L, int i, int e)
{int j;//插入之前首先判满if (L->length == Maxlength)//注:=为赋值符号;而数学等号为=={printf("fuck!顺序表已满!\n");return;}//判断插入位置是否合法if (i<1 || i>L->length + 1)//length + 1因为可以在表的末尾加,也即是最后一个序号为length的元素后面{printf("插入位置错误!\n");return;}//插入位置之后的所有元素都要向后移动一个位置for (j = L->length - 1; j >= i - 1; j--)//j = L->length - 1将j初始化为顺序表中最后一个元素的下标{                                     //循环条件j >= i - 1保证了只有从待插入位置开始之后的所有元素才需要被移动L->data[j + 1] = L->data[j];//后移  //循环语句j--将j逐渐减小,}L->data[i - 1] = e;//插入eL->length++;//表的长度加一return;
}

乍一看,代码很复杂,实则是前面AddList,DateSearch思想的结合

核心思想:1.插入相当于特定位置的增加,开始操作前毋庸置疑的判满2.你要告诉程序,在顺序表的什么位置,插入数值为多大的元素。所以需要,插入位置,插入数据元素的值,顺序表L三个参数,3.判断插入位置是否合法(同DateSearch思想)4.顺序表中元素是一个接一个有序排列,插入就跟排队时加塞一样(如下图),从要插入位置到最后一个元素,每个都要后移一位5.存入元素6.表长+1

/后移操作/

若如实际插队一样从前向后挨个后移,L->data[j + 1] = L->data[j];就会发现,最后一个元素被倒数第二个覆盖掉了,为了避免这一情况,从最后一个元素向开始后移才是正解。

// 删除

void DeleteList(List* L, int i)
{//不用判空,因为在判断位置是否合法的时候就已经判断了是否是空的 //判断删除位置是否合法if (i<1 || i>L->length + 1){printf("插入位置错误!\n");return;}int j;  //  将插入位置进行后移操作for (j = i; j < L->length; j++){L->data[j - 1] = L->data[j];//前移}L->length--;//长度-1return;
}
核心思想:1.判断删除位置是符合法(核心同按序号查找)2.元素前移3.表长-1

/无需判满/

添加要判满,但删除不用判空。在判断位置是否合法时,就已经判断了是否是空的。顺序表为空,length为0,带入if (i<1 || i>l->length + 1),条件成立,直接返回空,不会进入接下来的循环。

/前移/。

与后移思想相同,为了数据不被覆盖,要从删除位置后一个元素开始前移

// 逆置

//逆置
void InverList(List* L, int Maxsize)//Maxsize为最大元素的序号
{int i;int temp;for (i = 0; i < Maxsize / 2;i++){temp = L->data[i];L->data[i] = L->data[Maxsize - 1 - i];//Maxsize-1,为数组的下标,数组下标首尾进行交换L->data[Maxsize - 1 - i] = temp;}return;
}
核心思想:相当于两个数做交换1.在循环体中,temp变量暂存顺序表中第i个元素的值2.然后将第i个元素和对应的最后一个元素进行交换,即将第i个元素的值赋给L->data[Maxsize - 1 - i]3.Maxsize-1-i位置上的元素赋值为temp,完成了两个位置上元素的交换操作

// 打印顺序表长度

int LengthList(List L)
{return L.length;
}
核心思想:1.可直接打印length2.此处利用面向对象的封装思想,将其封装成函数

//----------------------------------------帅哥美女都点这里----------------------------------------

好吧,这是一段结束语,

以上就是小编对顺序表的理解,不同于教材以及其他参考代码的是小编结合自己学习中出现的问题,以贴近初学者的思维进行剖析,希望能对大家有所帮助。今后小编会随着学习进度,逐步更新内容,(计划上线完整的数据结构与C语言—小白式教学)希望大家多多支持,我们一起提高,共同成长。

创作不易,请看官老爷们给小编点一个赞吧

顺序表基本操作<小白一听就懂!!!><超详细><接地气>相关推荐

  1. 顺序表基本操作函数总结

    /*************************************************************************************/ /*   顺序表基本操作 ...

  2. PTA第一章作业1--数据结构基本概念 顺序表基本操作

    6-2 顺序表基本操作 (10分) 本题要求实现顺序表元素的增.删.查找以及顺序表输出共4个基本操作函数.L是一个顺序表,函数Status ListInsert_Sq(SqList &L, i ...

  3. 数据结构线性表的逻辑结构(三)顺序表基本操作的实现

    一. 实验目的 1. 掌握线性表的逻辑结构: 2. 顺序表基本操作的实现: 3. 掌握利用C/C++编程语言实现数据结构的编程方法: 4. 通过上机时间加强利用数据结构解决实际应用问题的能力: 二.  ...

  4. 【PTA】6-1 顺序表基本操作(10 分)

    题目来自 网络与信息安全-数据结构作业1-数据结构基本概念 6-1 https://fancyking.ml/archives/71 原题描述 6-1 顺序表基本操作(10 分) 本题要求实现顺序表元 ...

  5. 6-2 顺序表基本操作 (10 分)

    6-2 顺序表基本操作 (10 分) 本题要求实现顺序表元素的增.删.查找以及顺序表输出共4个基本操作函数. L是一个顺序表, 函数Status ListInsert_Sq(SqList &L ...

  6. 6-2 顺序表基本操作 (10分)

    6-2 顺序表基本操作 (10分) 本题要求实现顺序表元素的增.删.查找以及顺序表输出共4个基本操作函数.L是一个顺序表,函数Status ListInsert_Sq(SqList &L, i ...

  7. 6-1 顺序表基本操作(10 分)

    6-1 顺序表基本操作(10 分) 本题要求实现顺序表元素的增.删.查找以及顺序表输出共4个基本操作函数.L是一个顺序表,函数Status ListInsert_Sq(SqList &L, i ...

  8. 顺序表基本操作实现(详细)

    顺序表的目录 1.顺序表的概念 2. 熟悉顺序表的分类? 3.熟悉顺序表的优缺点 4.动态顺序表的基本操作 4.0包含头文件和结构体 4.1初始化,销毁,扩容 4.2尾插,尾删,头插,头删 4.3任意 ...

  9. 数据结构算法实现-顺序表基本操作

    数据结构算法实现 实现了高一凡的<<数据结构>>,书中的代码是基于VC6++ c++语言实现的,网上也可以找到TC版的c语言实现的源代码,TC版的源代码平台是 Turbo C ...

最新文章

  1. 如何使用OWASP Dependency Check的命令行(CLI)模式进行依赖库安全漏洞扫描
  2. getBoundingClientRect计算页面元素的offsetLeft、offsetTop
  3. C、C++中的逻辑运算符
  4. 招行率先落地房贷新政 其他银行细则仍在制定
  5. 四旋翼无人机调研结果
  6. linux内核路由反向检查,Linux路由设置 反向路由设置
  7. Sting中方法举例
  8. python中如何获取类的属性,python – 获取类的属性
  9. Nginx初探索之安装、启动、关闭和重启
  10. Python基础——timeit模块
  11. JavaWeb中的问题 ---- Servlet和Jsp
  12. 加密WebSphere Application Server系统密码
  13. 高德地图完整功能的html,关于高德地图WEB版基础控件的展示
  14. Dubbo本地存根是什么,Dubbo本地伪装又是什么?
  15. 【课程作业】学术英语写作:文献阅读报告2
  16. 阿里云体验--搭建超级小班课网课系统
  17. JDK下载过慢的问题解决方案
  18. 密码学常见困难问题DLP,CDH,DDH,GDH,BDH,CBDH,DBDH,GBDH,更新中
  19. 教学管理系统的设计与实现(一)(源码,以及毕业论文)
  20. 软考知识点---10数据库基础

热门文章

  1. ThinkPad T440s
  2. 反编译C语言程序学习笔记
  3. 嵌入式实验(四):用STM32输出PWM波形/DAC功能完成波形输出
  4. flutter 获取appbar高度,状态栏高度
  5. Linux vim替换命令
  6. 手机连接不上Charles代理解决方法
  7. 游戏建模行业市场井喷式爆发,你还在闷头死磕?
  8. 喷气大脑(jetBrain)快捷键指南
  9. 使用python将地名转换成经纬度——调用高德地图API
  10. hexo 设置多级目录,相关总结