线性表是数据结构中的一种基本结构,但是在线性表的顺序存储结构的一些基本运算中,涉及到C++里的引用,对C语言的学习者可能带来一些困惑,下面就具体操作一下线性表,来实现一些基本运算,体会其用法(下都称为线性表)

目录

  • 基本运算:
  • int * a 和 int &a:
  • SqList * L 和 SqList * &L的区别:

基本运算:

  1. 始化线性表InitList(&L) :构造一个空的线性表 L 。
  2. 销毁线性表DestroyList(&L) :释放线性表 L 占用的内存空间。
  3. 判线性表是否为空表ListEmpty(L) :若 L 为空表,则返回真,否则返回假。
  4. 求线性表的长度ListLength(L) :返回 L 中元素个数。
  5. 输出线性表DispList(L): 当线性表 L 不为空时,顺序显示 L 中各节点的值域。
  6. 求线性表 L 中指定位置的某个数据元素GetElem(L,i,&e) :用 e 返回L 中第 i 个元素的值。
  7. 定位查找LocateElem(L,e) :返回 L 中第一个值域与 e 相等的逻辑位序。若这样的元素不存在,则返回值为 0 。
  8. 插入数据元素 ListInsert(&L,i,e) : 在 L 的 第 i 个元素之前插入新的元素 e ,L 的长度增 1
  9. 删除数据元素 ListDelete(&L,i,&e) :删除 L 的第 i 个元素,并用 e 返回其值,L 的长度减 1

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct{        //创建一个顺序表 int data[100];    //放元素 int length;       //线性表长度} SqList;void InitList(SqList *&L) // 初始化顺序表 ,引用型指针
{  L=(SqList *)malloc(sizeof(SqList)); //分配存放线性表的空间 L->length=0;
}   //本算法的时间复杂度为 O(1) 。 顺序表 Lvoid DestroyList(SqList *&L)  //销毁线性表
{       free(L);      }  bool ListEmpty(SqList *L) //判断线性表是否为空 
{    return(L->length==0); } int ListLength(SqList *L)//求线性表的长度
{    return(L->length);   } void DispList(SqList *L)  //输出线性表
{ int i;if (ListEmpty(L))return; for (i=0;i<L->length;i++)printf("%d ",L->data[i]);printf("\n");
}void CreateList(SqList *&L,int a[],int n) //建立顺序表
{int i;    L=(SqList *)malloc(sizeof(SqList));  //L为SqListd的结构体类型的指针 , 就是一个线性表.for (i=0;i<n;i++)  L->data[i]=a[i];    //把数组a中的值都放入线性表L的data数组中L->length=n;
}bool GetElem(SqList *L,int i,int &e)  //得到顺序表中某位置元素的值。&e 就是引用
{ if (i<1 || i>L->length)  return false;     // i不在范围内e=L->data[i-1];       //e就改变了, return true;
} // 本算法的时间复杂度为 O(1) int LocateElem(SqList *L, int e)  //输出线性表中第一个与e相等的元素的位置{ int i=0; while (i<L->length && L->data[i]!=e) i++; if (i>=L->length)  return 0; else  return i+1; }bool ListInsert(SqList *&L,int i,int  e) // 向线性表中插入元素
{  int j;   if (i<1 || i>L->length+1) return false; //参数错误时返回false   i--; //将顺序表逻辑序号转化为物理序号 for (j=L->length;j>i;j--) //将data[i..n]元素后移 一个位置L->data[j]=L->data[j-1];  L->data[i]=e; //插入元素e   L->length++; //顺序表长度增1   return true; //成功插入返回true
}bool ListDelete(SqList *&L,int i,int &e) //删除元素
{   int j;if(i<1||i>L->length) //参数错误时返回false return false;   i--; //将顺序表逻辑序号转化为物理序号   e=L->data[i];   for (j=i;j<L->length-1;j++)  //将data[i..n-1]元素前移 L->data[j]=L->data[j+1];  L->length--;  //顺序表长度减1   return true;  //成功删除返回true
}//平均时间复杂度为 O(n) 。int main(){int b[11]={1,3,4,6,3,15,6,35,61,21,19};int e=12;SqList *L;// InitList(L) //初始化线性表,分配内存空间 //初始化的功能合并到创建线性表中了。CreateList(L,b,11);DispList(L);//输出线性表printf("\n");GetElem(L,3,e); //得到线性表第三个元素的值,放在e中 printf("线性表第三个元素的值 e = %d\n",e);//看e是否改变 printf("\n");e=6;int locate = LocateElem(L,e);//看看数字第一个6 在线性表的哪个位置。printf("第一个6 在线性表 locate = %d\n",locate);printf("\n");ListDelete(L,8,e); //删去线性表第8个数字,删去的数字在e中存放。printf("删去的数字 e = %d\n",e);printf("\n");DispList(L);//输出线性表 }

运行结果为:

我们可以看到,在定义时,有许多类似于:

bool GetElem(SqList *L,int i,int &e)
bool ListDelete(SqList *&L,int i,int &e)
//这里我们看到的 *&L和 *L, 还有之前C语言中 int *a 和这里 int &a下面我们看这个


int * a 和 int &a:

int a; int &ra=a; //定义引用ra,它是变量a的引用,即别名

说明:

(1)&在此不是求地址运算,而是起标识作用。

(2)类型标识符是指目标变量的类型。

(3)声明引用时,必须同时对其进行初始化。

(4)引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,且不能再把该引用名作为其他变量名的别名。

ra=1; 等价于 a=1;

(5)声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。故:对引用求地址,就是对目标变量求地址。&ra与&a相等。

(6)不能建立数组的引用。因为数组是一个由若干个元素所组成的集合,所以无法建立一个数组的别名。

#include<stdio.h>
void Fun1(int &e)
{e=9;
}void Fun2(int *e)
{*e=9;
}int main()
{int a = 5;
Fun1(a);
printf("%d\n",a);
a=5;
Fun2(&a);
printf("%d\n",a);
return 0;
}

这两个函数的最后效果是一样的,都改变了a的值。但是在函数中,参数表示的意思是不一样的。
第一个函数当中,e是一个整形变量;在第二个函数当中e是一个整形指针变量

所以有一下两点:

  • 传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。

  • 使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用"*指针变量名"的 形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。

更多相关应用的知识请看C++基础——引用的学习



SqList * L 和 SqList * &L的区别:

*L是指针,全称是指针变量,是一个用来保存内存地址的变量。在这里是一个指向顺序表,存储顺序表的地址的变量。

*&L是指针类型的引用,引用(reference)是c++对c语言的重要扩充。引用就是原变量的另外一个名称(别名),引用变量本身没有自己的实际存储空间,对引用变量的操作,就是在操作原变量。这里的 *&L 代表原指针。

这两个有着一个共同点,都指向顺序表 L ,如果在函数中修改L 的内容,都影响到 L 的内容。

不同点则是,在函数中修改指针本身所指向的地址,* L 不会发生改变,而 * &L会发生改变。

若要改变形参中的内容并且使用它则需要用引用,如果不需要改变子函数体中形参旳值,则不需要用引用。

首先,* &L是引用类型的指针,代表的是原指针,我们在函数中对指针的操作,都是直接对原指针的操作,无论是指针的内容,还是指针指向的地址,都会发生改变。

那么,*L为什么在函数中会改变不了所指向的地址呢?

其实,这里我们要延伸到函数形式参数和实际参数的很基础,也很重要的知识点了。

形参出现在函数定义中,在整个函数体内都可以使用。实参出现在主调函数中,进入被调函数后,实参也不能使用。在函数调用的时候,主函数把实参的值传送给被调函数的形参,从而实现数据的传送。

但是,在这个函数调用的过程中,数据传送是单向的,即数据只能由实参传到形参,而形参不会传回实参。也就是说,我们在函数中改变形参的值,实参的值是不会发生改变的,这就是函数调用中的单向值传递。

那么,回到我们的 *L 来,*L其实就是一个变量,在这里是一个形式参数。形式参数在函数中其实是对实参的拷贝,也就是说,函数中形参其实是另一个变量,一个复制原变量的新变量,有不同于原变量的内存空间,存在于函数中,函数调用结束,即刻释放内存空间。

也就是说,我们在函数中改变 *L 所指向的地址,不是在对原变量进行改变,而是对原变量的一个复制体进行改变,改变了复制体,却没有改变本体。

所以,在函数中 *L 不能改变所指向的地址。

数据结构——顺序表 SqList *L 和 SqList * L的区别相关推荐

  1. 数据结构顺序表中Sqlist *L,L,Sqlist *L

    //定义顺序表L的结构体 2 typedef struct 3 { 4 Elemtype data[MaxSize]: 5 int length; 6 }SqList; 7 8 //建立顺序表 9 v ...

  2. C语言/C++常见习题问答集锦[八十三]之数据结构顺序表(operand types are error: no match for “operator==“)

    C语言/C++常见习题问答集锦[八十三]之数据结构顺序表{operand types are error: no match for "operator=="} 程序之美 前言 主 ...

  3. 数据结构--顺序表、链表、栈、队列、树、文件(visual studio可运行)

    顺序表的顺序存储(增删查) #include <stdio.h> #include <stdlib.h> #define MaxSize 50 typedef int Elem ...

  4. 【详细注释】数据结构 顺序表的增删查 C/C++实现

    前言 顺序表将数据存储在计算机内存中的相邻存储单元内,故结构体内部存储直接使用数组即可. 代码实现 /*** 请注意,由于本次实现需要用到bool变量以及引用,请创建* C++文件而不是C文件*/#i ...

  5. 数据结构-顺序表结构的实现C语言(全代码)

    课程设计题目 设计出顺序表结构的相关函数库,以便在程序设计中调用. 题目要求 (1)包括线性表的各种基本函数以及常用函数(自己确定函数.函数形式及理由) (2)最好能借助语言环境实现图形显示功能,以便 ...

  6. Educoder头歌数据结构顺序表及其应用

    头歌实践平台答案educoder 数据结构-顺序表及其应用 第1关:顺序表的实现之查找功能 /***************************************************** ...

  7. 数据结构--顺序表--史上最全--王道考研笔记

    顺序表 定义 顺序表采用顺序存储方式,是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系 第n个元素 第n个元素的存放位置 ...

  8. C语言链表的转置算法,c语言编程集 数据结构 顺序表 点链表 数制转换 矩阵转置.doc...

    c语言编程集 数据结构 顺序表 点链表 数制转换 矩阵转置 #include "stdio.h" #include "malloc.h" /*typedef s ...

  9. 数据结构-顺序表(动态分配存储空间)

    数据结构-顺序表(动态分配存储空间) (1)顺序表的结构定义: 结构型定义:(动态分配存储空间) /*** 动态分配存储空间*/ #define InitSize 100 //动态分配存储空间时,不限 ...

  10. 数据结构--顺序表的使用

    数据结构--顺序表的使 #include<iostream> #include<cstdio> #include<cstring> using namespace ...

最新文章

  1. 带宽与码元的关系_带宽、速率(波特率、比特率)和码元宽度简述
  2. html5圆形图片轮播,jQuery超酷响应式圆形图片轮播图特效
  3. ML近三年在CVPR比较流行被应用的技术有哪些?
  4. Qt中使用C++的方式
  5. 模拟网络通信中存储转发的分组交换算法
  6. 苹果原壁纸高清_周易壁纸 | 八卦图阵高清壁纸
  7. 基于Spring boot+Vue的在线考试系统
  8. Windows编程的Notification和Message
  9. 社会化生态农场品,社群+农产品,大有搞头
  10. windows破解锁屏密码(亲测有效:再也不怕别人锁屏防你啦!)
  11. 【墨墨英语单词库免费开源无偿分享】小学、初中、高中、大学四六级专四专八、考研、托福、雅思等词书文本大合集
  12. vivo Y51的USB调试模式在哪里,开启vivo Y51USB调试模式的教程
  13. 通过rundll32调用系统对话框
  14. json文件是什么?
  15. Vue定义全局常量,全局方法
  16. win7下LInux虚拟机搭建
  17. 厦门八大美院墙绘 茶馆里的中国风墙绘壁画
  18. 制作室内效果图必不可少的因素有哪些?
  19. java 发起HTTPS请求-SSL客户端
  20. 人间还是仙界?聊一聊linux系统的用户空间和内核空间

热门文章

  1. ctfmon是什么启动项_Windows7系统启动项里没有ctfmon.exe怎么办?
  2. PropertyUtils.copyProperties 属性值复制失败
  3. SD-Host 控制器设计
  4. 在Ubuntu18.04中安装ROS教程
  5. Android签名概要总结——对称加密/非对称加密、数字签名、公钥证书、ca认证机构、安卓app签名
  6. 最简单的WIN7内核PE系统的U盘安装方法+WIN7密码破解
  7. 除了WhatsApp以外,还有哪些即时聊天软件?
  8. Spark SQL 之开窗函数
  9. mysql安装和基本操作
  10. 无线扫码枪 服务器查询异常,扫描枪常见问题