首页 > 编程知识 正文

数据结构顺序表存储结构,数据结构while

时间:2023-05-03 22:16:38 阅读:160527 作者:1560

3358www.Sina.com/是数据结构中的基本结构之一,但是在线性表的线性表的一些基本运算中,涉及c的顺序存储结构,向c语言的学习者提供

基本运算: int * a和int a:SqList * L和SqList * L的差异:

运算:初始化路线列表initlist(L ) :创建空路线列表l。 放弃线性列表destroylist(L ) :释放线性列表l占用的内存空间。 判定线形表是否为空表的listempty(L ) :如果l为空表则返回真,否则返回假。 求线性表的长度listlength(L ) :返回l中元素的个数。 输出线性列表displist(l ) :线性列表l不为空时,依次显示l中各节点的值域。 求路线图l中指定位置的数据要素getelem(L,I,e ) :用e返回l中第I个要素的值。 查找locateelem(L,e ) :返回l的第一个值域等于e的逻辑比例。 如果不存在这样的元素,则返回值为0。 插入数据元素listinsert(L,I,e ) :在l的第I个元素之前增加新元素e,l的长度1以删除数据元素ListDelete(L ) l,I,e :删除l的第I个元素并在e中返回其值的长度到1 # include stdio.h # include string.h # include stdlib.htypedefstruct {//顺序表int data[100]; //加入元素int length; //线性表长度(} SqList; voidinitlist(sqlist*L ) /初始化顺序表,引用类型指针(L=) sqlist* ) malloc ) sizeof ) sqlist ); L-length=0,分配用于存储线性表的空间; //本算法的时间复杂度为o(1)。 顺序表Lvoiddestroylist(sqlist*L ) /放弃线性表) free(L ); }boollistempty(SQList*L ) /确定线索表是否为空(return ) L-length==0); (intlistlength ) SQList*L ) /求出线形表的长度) return(L-length ); }voiddisplist(sqlist*L ) /输出线形表({ int i; 列表元素(l ) )返回; for(I=0; iL-length; I ) printf('%d ',L-data[i]; 打印((n ); }voidcreatelist(sqlist*L,int a[],int n ) /创建顺序表(intI; L=(sqlist* ) malloc (sizeof ) sqlist ); //L是SqListd的结构体类型的指针,表示线形表. for(I=0; in; I ) L-data[i]=a[i]; //将数组a的值全部放入线形表l的data数组中的L-length=n; }boolgetelem(sqlist*L,int i,int e ) /得到顺序表某个位置的要素的值。 e是指{if(I1||il-Length ) return false; //i超出范围e=L-data[i-1]; //e变了,返回真; //本算法的时间复杂度为o(1) intlocateelem ) SQList*L,int e )//输出线性表中等于前e的元素的位置(intI=0; while(il-lengthL-data[I]!=e ) I; if(I=L-Length ) return 0; else return i 1; }boollistinsert(sqlist*L,int i,int e )//在路线图中插入元素(intj; if(I1||il-Length1)返回假; //如果参数错误,则返回false i--; //将顺序表的逻辑编号转换为物理编号for (j=l-length; ji; 将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 = %dn",e);//看e是否改变 printf("n");e=6;int locate = LocateElem(L,e);//看看数字第一个6 在线性表的哪个位置。printf("第一个6 在线性表 locate = %dn",locate);printf("n");ListDelete(L,8,e); //删去线性表第8个数字,删去的数字在e中存放。printf("删去的数字 e = %dn",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("%dn",a);a=5;Fun2(&a);printf("%dn",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 不能改变所指向的地址。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。