线性表的顺序存储
2015-03-13 09:47
183 查看
线性表的顺序存储,其数据结构以及具体实现详见下面代码,重要知识点全部以注释的形式在代码中展示出来。
/*** 线性表的顺序存储结构是一种随机存取的存储结构 在线性顺序表中插入或者删除一个元素,时间都消耗在移动元素上,平均约移动一般的元素, 故ListInsert和ListDelete的时间复杂度都为O(n); */ #include<stdio.h> #include<stdlib.h> //***************线性表的动态分配顺序存储结构***************** #defineLIST_INIT_SIZE100//线性表存储空间的初始分配量 #defineLISTINCREMENT10//线性表存储空间的存储增量 typedefstruct { int*elem;//数组指针,存储空间基址 intlength;//当前长度 intlistsize;//当前分配的存储容量(以sizeof(int)为单位) }SqList; //******************初始化线性表,构造一个空表******************** voidInitList(SqList&L) { L.elem=(int*)malloc(LIST_INIT_SIZE*sizeof(int)); if(!L.elem) { printf("存储分配失败,任意键退出!\n"); getchar(); exit(1); } L.length=0; L.listsize=LIST_INIT_SIZE; } //*********************输出线性表中的数据************************** voidPrintList(SqListL) { int*p=L.elem;//顺序表的开始位置 int*q=L.elem+L.length-1;//顺序表的结束位置 while(p<=q) { printf("%d",*p++); } } //*************************线性表的插入**************************** //*******参数i代表插入位置,在第i个之前插入*,故1<=i<=n+1********* /** 一般情况下,在第i(1<=i<=n)个元素之前插入,需要将第i至n(n-i+1)个元素向后移动一个位置, 若i=n+1,则直接在插入在最后即可 */ voidListInsert(SqList&L,inti,inte) { //在顺序线性表L中的第i个位置之前插入新的元素e //i的合法值为1<=i<=ListLength(L)+1 if(i<1||i>L.length+1) { printf("输入的插入位置不合法,请确定后重新输入!任意键退出\n"); getchar(); exit(1); } if(L.length>=L.listsize) { //当前存储空间已满,需要增加分配 int*newbase=(int*)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(int)); if(!newbase) { printf("存储分配失败,任意键退出!\n"); getchar(); exit(1); } L.elem=newbase;//新基址 L.listsize+=LISTINCREMENT;//增加存储容量 } int*q=&(L.elem[i-1]);//q为插入位置 for(int*p=&(L.elem[L.length-1]);p>=q;--p) { *(p+1)=*p;//插入位置及其之后的元素右移 } *q=e;//插入e ++L.length;//表长加1 } //***************************顺序线性表的删除****************************** /** 参数i代表删除位置,1<=i<=n,和插入时i的取值范围不同 一般情况下,删除第i(1<=i<=n)个元素时需要将从第i+1至第n(n-i)个元素依次向前移动一个位置 */ voidListDelete(SqList&L,inti) { //删除顺序线性表中的第i个元素,i的合法值为1<=i<=ListLength(L) if(i<1||i>L.length) { printf("输入的删除位置不合法,请确定后重新输入!任意键退出!\n"); getchar(); exit(1); } int*p=&(L.elem[i-1]);//p为删除位置 int*q=L.elem+L.length-1;//q为表尾位置 for(++p;p<=q;++p) { *(p-1)=*p;//被删除元素之后的元素左移 } --L.length;//表长减1 } //************数值定位函数,返回元素e在L中的位置,若没有,返回0*************** intLocateElem(SqListL,inte) { //在顺序线性表中查找第一个与元素e相同位序 //若找到,则返回其在L中的位序,否则返回0 inti=1;//i的初始值为第一个元素的位序 int*p=L.elem;//p的初始值为第一个元素的存储位置 while(i<=L.length&&e!=*p) { ++i; ++p; } if(i<=L.length) returni; else return0; } //**********************取出指定位序的线性表中的数据元素*********************** intGetElem(SqListL,inti) { //将线性表L中的第i个元素返回给e if(i<1||i>L.length) { printf("该数据元素不存在,请仔细确认!任意键退出\n"); getchar(); exit(1); } //int*q=&L.elem[i-1]; //inte=*q; inte=L.elem[i-1]; //因为elem是一个数组指针,当只用elem时,代表首地址 //,若具体指定某一个数elem[i],则代表第i+1个元素,故下面和上面的注释方法都可行 //int*p=L.elem; //inte=*(p+i-1); returne; } //****************************线性顺序表的合并******************************** /** 该方法的线性复杂度为O(ListLength(LA)xListLength(LB)) 该方法得到的线性表是无序的,数据直接插在一个线性表的最后 是将所有在线性表Lb中但不在La中的数据元素插入到La中,无重复项 */ voidListUnoin(SqList&La,SqListLb) { //将所有在线性表Lb中但不在La中的数据元素插入到La中 intla_len=La.length; intlb_len=Lb.length; inte; for(inti=1;i<=lb_len;++i) { e=GetElem(Lb,i);//取Lb中第i个元素赋值给e //printf("%d\n",e); if(!LocateElem(La,e)) { ListInsert(La,++la_len,e);//将数据插在La的末尾 } } } //**************************有序线性顺序表的合并******************************* /** 通过增加一个线性表,使得时间复杂度由O(ListLength(LA)xListLength(LB))变成 了O(ListLength(LA)+ListLength(LB)) 不过使用这种方法需要有个前提:La和Lb已经排序 得到的结果Lc也是排好序的线性表 */ voidMergeList(SqListLa,SqListLb,SqList&Lc) { //本例中以非递减排序为例 int*pa=La.elem; int*pb=Lb.elem; Lc.length=La.length+Lb.length; Lc.listsize=Lc.length; Lc.elem=(int*)malloc(Lc.listsize*sizeof(int)); if(!Lc.elem) { printf("存储分配失败,任意键退出!\n"); getchar(); exit(1); } int*pc=Lc.elem; int*pa_last=La.elem+La.length-1; int*pb_last=Lb.elem+Lb.length-1; while(pa<=pa_last&&pb<=pb_last)//归并操作 { if(*pa<=*pb) *pc++=*pa++; else *pc++=*pb++; } while(pa<=pa_last) *pc++=*pa++;//插入La的剩余元素 while(pb<=pb_last) *pc++=*pb++;//插入Lb的剩余元素 } intmain() { //首先输入10个数据,构造一个线性表,测试建表,输出,插入,删除功能是否正确 SqListLa,Lb,Lc; InitList(La); InitList(Lb); InitList(Lc); intcount,value,location; printf("请输入建立顺序表La的元素个数:"); scanf("%d",&count); printf("请依次输入%d个数据:",count); for(inti=0;i<count;++i) { //将输入的数据插入到顺序表La中 scanf("%d",&value); ListInsert(La,i+1,value); } //输出线性表的数据 printf("该顺序线性表的数据元素为:"); PrintList(La); //测试插入数据是否可行 printf("\n请输入插入位置和插入值:"); scanf("%d%d",&location,&value); ListInsert(La,location,value); printf("插入之后的数据元素为:"); PrintList(La); //测试删除数据情况 printf("\n请输入删除位置:"); scanf("%d",&location); ListDelete(La,location); printf("数据删除之后的元素为:"); PrintList(La); //测试顺序表的合并,需要两个有序的顺序表 printf("\n请输入建立顺序表Lb的元素个数:"); scanf("%d",&count); printf("请依次输入%d个数据:",count); for(inti=0;i<count;++i) { //将输入的数据插入到顺序表La中 scanf("%d",&value); ListInsert(Lb,i+1,value); } MergeList(La,Lb,Lc); printf("将La和Lb合并之后的Lc数据元素为:"); PrintList(Lc); printf("\n采用时间复杂度更高的合并方式为:"); ListUnoin(La,Lb); PrintList(La); return0; }