顺序表的定义与操作实现
来源:互联网 发布:wifi连网神器mac版 编辑:程序博客网 时间:2024/06/01 09:50
#include <stdio.h>#include <stdlib.h>//malloc()#define OK 1#define ERROR 0#define TURE 1 #define FALSE 0#define INFEASIBLE -1 //不可行的#define OVERFLOW -2 //溢出#define LIST_INIT_SIZE 100//初始分配的元素个数(这些数据都是自己定义的,可以根据实际情况来分配)#define LIST_ADD_SiZE 10//分配增量typedef char ElemType;//表明ElemType是 char 类型//========================线性表的动态分配存储结构====================typedef struct{ ElemType *elem;//指针型变量,存储空间的起始地址 int length;//当前的长度(存储的数据个数) int listsize;//当前分配的存储容量}SqList;//基本操作定义//==========================InitList()初始化函数======================int InitList(SqList &L){ L.elem=(ElemType *)malloc(LIST_INIT_SIZE*sizeof(LIST_INIT_SIZE));//用指针elem存储分配的线性表的起始地址 if(!L.elem) exit(OVERFLOW);//由于某种原因,内存分配失败 L.length=0;//初始化时候最初存储的元素个数为0 L.listsize=LIST_INIT_SIZE; return OK;}//==========================ClearList()重新设置为空表==================int ClearList(SqList &L){ L.length=0; return OK;}//==========================ListEmpty()判断是否为空================================int ListEmpty(SqList L){ if(L.length==0) return TURE;//为空,返回TURE else return FALSE;//不为空,返回FALSE}//==========================ListLength()返回线性表的长度=====================================int ListLength(SqList L){ if(!L.elem) return ERROR; return L.length;}//==========================GetElem()用e返回第i个数据元素的值================================ElemType GetElem(SqList L,int i,ElemType &e){ if(i<1 || i>L.length || !L.elem) //查找的位置越界或L表不存在,返回错误 return ERROR; e=*(L.elem+i-1);//蛋蛋,这里要明白的是:L.elem表示的是 return e; }//==========================LocateElem()返回所找元素在表中的位置================================int LocateElem(SqList L,ElemType e,int(*compare)(ElemType,ElemType)){ int i=1;//这里的i=1,和下面的while语句相呼应,表明的是检测【1......L.length】共length个元素 ElemType *p; p=L.elem;//指针p存储表L的首元地址,如果用指针p做相应操作(比较),相当于直接用L.elem指针一样 while(i<=L.length && !(*compare)(*p++,e))//表中的元素和e想等时,用i记下那个位置 ++i; if(i<=L.length) //注意:上面一句,是++i;因此,当最后一个元素和e比较不等时,i仍然+1,此时i>L.length【不应该输出这个i】,所以要限制为i<=L.length return i; else return FALSE;}//==========================GetElem()用e返回第i个数据元素的值================================int compare(ElemType e1,ElemType e2){ if(e1==e2) return TURE; else return FALSE;}//==========================PriorElem()返回cur_e的前驱元素================================//若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,否则操作失败int PriorElem(SqList L,ElemType cur_e,ElemType &pre_e){ //关键是找到值为cur_e的元素位置 int i=2; ElemType *p=L.elem+1;//p存储第二个元素的地址 while(i<=L.length && *p!=cur_e)//没找到,执行...... { p++; //p指向下一个元素 i++; } if(i>L.length) //如果i>length时还没找到,则返回“不可行” return INFEASIBLE; else { //*--p表示先让指针减1,再取其值,所以下面用()把--p扩住,括号的运算优先级大于*运算符 //在这里强烈建议一定要看C prime Pluse 第十章{数组和指针} pre_e=*(--p); //当找到(while循环结束),赋给pre_e return OK; }}//==========================NextElem()用next_e返回cur_e的后继元素================================int NextElem(SqList L,ElemType cur_e,ElemType &next_e){ int i=1; ElemType *p=L.elem; while(i<L.length && *p!=cur_e)//比较【1......length-1】共length-1个元素 { i++; p++; } if(i==L.length) return INFEASIBLE;//注意:已经找到了最后一个元素(最后一个元素没有后继),还没找到,返回“不可行” else { next_e=*(++p); return OK; }}//==========================ListInsert()在第i个位置之前插入元素e================================/*顺序表是从0开始的一种存储单位连续的数据结构,它如果有i个元素最后一个元素下标就为i用数组来存储顺序表的元素数据,数组从【0】开始【i-1】结束,顺序表的第i个元素的数组下标是【i-1】*///操作结果:成功插入,length+1int ListInsert(SqList &L,int i,ElemType e){ ElemType *newbase,*q,*p; if(i<1 || i>L.length+1)//从表的第一个元素开始可以插入,在表的最后一个元素的后面也可插入元素,符合则执行 return ERROR; //在已经有数据的基础上,表已经满了,则考虑再分配存储空间 if(L.length>=L.listsize) { newbase=(ElemType *)realloc(L.elem,(L.listsize+LIST_ADD_SiZE));//插入元素要考虑内存空间空间是否足够 if(!newbase)//和分配L.elem时类似(某种原因导致分配错误) exit(ERROR); L.elem=newbase;//用elem存储新基址 L.listsize+=LIST_ADD_SiZE;//当前分配空间增加 } q=&(L.elem[i-1]);//用q记[i]位置的前一个位置[i-1]的元素 for(p=&(L.elem[L.length-1]);p>=q;--p)//逆序开始,把表的最后一个元素[length-1]到第[i-1]个元素处(注意范围,想一想为什么?) *(p+1)=*p;//元素统一往后移一个位置,可以画图表示出要移动的元素起始到结束的位置! *q=e;//表示e值放到指针所指的位置上 L.length++;//记得要让长度加1 return OK;}//==========================ListDelete()删除L中第i个数据,用e返回其值================================ElemType ListDelete(SqList &L,int i,ElemType &e){ ElemType *p,*q; if(i<1 || i>L.length) return ERROR; p=L.elem+i-1;//p为被删除元素的位置 L.elem+0相当于是L.elem[0] L.elem+i就相当于是L.elem[i] e=*p; q=&(L.elem[L.length-1]);//沿用插入操作的赋值方式,记录下表尾元素的位置 //++p 分析:p是指针,所以++p就是指针p指向下一个元素的位置 //遇到++i 和i++ 不要怕,弄清原则就很好理解!举个例子:C到C++ 先有C再有C++,++i表示先+1再使用。//如果这块有问题,还是看书彻底搞明白。 for(++p;p<=q;++p)//注:第一个++p表示for循环的起始位置(表示从第i个元素的后一个元素[i-1]开始向后移动一个位置),第二个++p表示进行的动作操作(自增) *(p-1)=*p;//这里的赋值其实是后面的值覆盖了前面的元素值。 L.length--; return OK;}//==========================ListTraverse()对每个数据元素调用vi()函数================================void ListTraverse(SqList L,void(*vi)(ElemType )){ ElemType *p; int i; p=L.elem;//指针p指向L的首元地址 for(i=1;i<=L.length;i++) vi(*p++);//依次对表中的每个元素执行Vi()函数 printf("\n");}//==========================vi()函数只是一个任意的你想对数据处理的函数功能,比如对int 型数据每个元素乘以2,对char型数据每个元素执行输出操作,可以参考那个资料================================//这里的vi仅实现对元素输出的操作void vi(ElemType e){ printf("%c ",e);}//==========================main()===========================================================int main(){ SqList L; ElemType e,e1; int i; int k; //执行初始化函数 InitList(L);//=====================这步是帮助理解的============== //执行完初始化函数后可以输出给L分配的空间基址和当前分配的空间大小 //其实这步可以帮助理解指针和存储相关的存储空间的知识 printf("%u %d 当前的元素个数:%d\n",L.elem,L.listsize,L.length);//无符号十进制输出 printf("%u \n",L.elem+1);//elem是指针,elem+1 就是指针指向下一个元素,这里测试的是char类型,char类型 占一个字节。通过输出可以一看出。地址+1 //同样的道理,如果这里存储的是int类型,int 类型占4个字节,下一个int元素的地址是上一个int元素地址+4。 //每个变量都占有一定数目的字节(通过sizeof运算符获得)其中取第一个字节的地址做该变量的地址。//=========================又啰嗦了,进入正题!============================================ //判断是否为空 if(ListEmpty(L)==TURE) printf("由于线性表的长度存储的元素个数是0,所以为空。\n"); else if(ListEmpty(L)==FALSE)//判断不为空,同时输出元素个数。 printf("不空。存储的元素个数是=>:%d\n",L.length); //接下来向表内手动插入元素 printf("请输入你要插入的元素个数=>:"); scanf("%d",&k); printf("请输入数据=>:"); for(i=1;i<=k;i++) { scanf(" %c",&e);//输入一个数据,把它插入到依次第i个元素之前 ListInsert(L,i,e); } //测试输出L里面的数据 ListTraverse(L,vi); printf("当前表的长度是:%d\n",ListLength(L)); printf("查找元素的位置(接下来请输入你要查找的元素)=>:"); scanf(" %c",&e); i=LocateElem(L,e,compare); if( i==FALSE) printf("表中没有该元素!\n"); else printf("你所找的元素%c在表中的位置是=>%d\n",e,i); //======================================================== //插入元素 printf("请输入你要插入的元素的位置和值=>:"); scanf(" %d %c",&i,&e); if(ListInsert(L,i,e)==ERROR) printf("错误!"); else { printf("成功插入%c后的表L=>:",e); //测试输出L里面的数据 ListTraverse(L,vi); } //============================================================ //删除元素 printf("请输入你要删除的元素在表中的位置=>:"); scanf(" %d",&i); ListDelete(L,i,e); printf("删除第%d个元素%c后表L=>:",i,e); ListTraverse(L,vi); //查找前驱元素的值 printf("请输入元素(查找该元素的前驱)=>:"); scanf(" %c",&e); PriorElem(L,e,e1); printf("元素%c的前驱是=>: %c\n",e,e1); //查找后继 printf("请输入元素(查找该元素的后继)=>:"); scanf(" %c",&e); NextElem(L,e,e1); printf("元素%c的后继是=>: %c\n",e,e1); ClearList(L); printf("执行清空表操作后,表长为=>:%d\n",ListLength(L)); return 0;}
0 0
- 顺序表的定义与操作实现
- 顺序表的定义与操作
- 线性表的定义与操作--顺序表
- 线性表的定义与操作-顺序表
- 顺序线性表的定义与基本操作
- 顺序表的类定义及其操作
- 顺序表的定义及基本操作
- 堆栈的定义与操作(顺序存储)
- 队列的定义与操作(顺序存储)
- 数据结构之 顺序表的实现与操作
- 1.1顺序表基本操作的设计与实现
- c语言顺序表的实现与基本操作
- 静态与动态顺序表操作的C语言实现
- 作业4--线性表类型定义与顺序表操作
- 线性表类型定义与顺序表操作
- 线性表类型定义与顺序表操作
- 二叉链表的定义与基本操作实现函数
- 线性表-顺序表和单链表的定义与基本操作
- 微信开发建站所需档案清单
- poj1243
- 队列和栈的使用
- c++第六次实验
- Integer的highestOneBit方法源码解析
- 顺序表的定义与操作实现
- linux 安装ffmpeg记录
- Android的MVP模式
- html参考手册--标签
- mac开发android 安卓真机调试解决方案
- 安装、配置和测试Asterisk过程中遇到的问题及解决方法
- Jdeveloper不能连接oracleXE
- 组合简便算法 (long long 与__int64)
- Restful接口设计