线性表的存储以及相关操作实现
来源:互联网 发布:cg软件有哪些 编辑:程序博客网 时间:2024/05/17 07:40
//以前的实验报告被我找到了,找知道还在就不用QQ空间上的截图了,代码很糟糕,那是因为本人还是菜鸟
一,顺序存储
内容:此线性表采用顺序存储,实现了初始化、建表、查找、删除、打印,清空,销毁,返回前去后继等功能。
---------------函数功能实现------------------void InitList(sqList *L){(*L).elem = (int*)malloc(LIST_INIT_SIZE*sizeof(int)); //申请空间,将首地址赋给表指针作为基址if(!(*L).elem) exit(0);//如果申请失败就退出(*L).length =0;//表长为空,无数据(*L).listsize =LIST_INIT_SIZE;//容量赋值}//创建空表void creatlist(sqList *L){int n,x,i;printf("请输入要存储的数据个数\n");scanf("%d",&n);printf("请输入数据:\n");for(i=1;i<=n;i++)//循环读入数据{scanf("%d",&x);(*L).elem[i] = x;}(*L).length = n;//别忘了为表长赋值}//输入数据int destroyList(sqList *L){ int i; if ((*L).elem)//线性表存在,则继续执行 { free((*L).elem); (*L).elem = NULL; printf("\n\n--线性表销毁完毕--\n"); } else {printf("\n\n--表不存在--\n");return FALSE;}//否则错误退出 return OK;}//销毁线性表void clearlist(sqList *L){ (*L).length=0; //将线性表的长度置为0 printf("\n\n--线性表清空完毕--\n");//清空即是让数据清空,表长为0即是无数据(可看上面)}//清空线性表int ListEmpty(sqList *L){ if ((*L).length==0)//同样道理,通过判定表长便可以确定线性表是否为空 { printf("\n\n线性表为空!!\n"); return TRUE; } else { printf("\n\n线性表不为空!!\n"); return FALSE; }}//判断线性表是否为空int ListLength(sqList *L){ printf("\n\n--线性表长度为:%d--\n",(*L).length);//没啥说的,直接返回线性表成员length的大小即可return ((*L).length);}//返回线性表长度int GetElem(sqList *L,int i,int e){ if (i<1||i>(*L).length) {return 0;} //判断i值是否合理,若不合理,返回ERROR else e = (*L).elem[i];//位序正确,即把对应的线性表成员中的元素elem[i]作为返回值 return e;}//返回特定位序的元素int LocateELem(sqList *L,int i,int e){ for (i=1;i <= (*L).length;i++)//结合上面的输入数据(creatlist)的函数,从1开始遍历 if ((*L).elem[i]==e) return i;//找到则返回1 if(i = (*L).length&&(*L).elem[i] != e) return ERROR;//找不到则返回0}//定位特定元素的位序int priorelem(sqList *L,int cur_e,int pre_e){ int i;if((*L).elem == NULL)//判断线性表是否存在,不存在则退出{printf("--表不存在--\n");exit(0);} for(i=1;((*L).elem[i]!=cur_e)&&(i<=(*L).length);i++);//利用for循环遍历 //循环出来之后即是elem[i]=cur_e if(i<=(*L).length) printf("\n--当前位序:%d--\n",i);//方便查看当前位置 else {printf("\n--位序过界--\n");return(FALSE);} if((*L).elem[i] == cur_e) pre_e = (*L).elem[i-1];//记录位序的前一个元素数据 else {printf("\n--%d不存在于表中--\n",cur_e);return (FALSE);} return pre_e;}//返回特定元素的前驱int nextelem(sqList *L,int cur_e,int next_e){int i=1; if((*L).elem == NULL){printf("--is null--\n");exit(0);}for(i=1;(*L).elem[i]!=cur_e&&i<=(*L).length;i++);if(i<=(*L).length) printf("\n--当前位序:%d--\n",i);if(i<(*L).length) next_e = (*L).elem[i+1];else {printf("\n--%d的后继不存在--\n",cur_e);return (FALSE);} return next_e;}//返回特定元素的后继int ListInsert_sq(sqList *L,int i,int e){ if(i < 1||i > (*L).length+1) { printf("\n--位序不存在,插入错误--\n");return ERROR;} if((*L).length >= (*L).listsize){ newbase=(int*)realloc((*L).elem, ((*L).listsize+LISTINCREMENT)*sizeof(int)); //空间不足,则增加空间然后将数据复制入新的存储空间 if(!newbase) exit(0);//空间申请失败,则退出 (*L).elem = newbase;//新基址(首地址) (*L).listsize += LISTINCREMENT; //增加存储容量 } q = &((*L).elem[i]);//q为插入位置 ++(*L).length;//关键:先将空间增一,那么length-1即是原表的最后一个位置 for(p = &((*L).elem[(*L).length-1]);p>=q;--p) *(p+1) = *p;//从(原)表尾开始右移 *q = e; return OK;}int ListDelete_sq(sqList *L,int i,int e){ if(i <1||i>(*L).length ) { printf("\n--位序不存在,无法删除--\n");return -1;} p = &((*L).elem[i]);//被删除元素位置 e = *p;//将被删除的元素的值赋给e q = (*L).elem + (*L).length;//表尾元素的位置 for(++p;p <= q;++p) *(p-1) = *p;//被删除元素的下一个开始左移 --(*L).length; return e;}//删除位序i的元素,并用e返回其值int ListTraverse(sqList *L){ int i; printf("\n列表如下:\n\n"); printf("位序 | "); for(i=1;i<=(*L).length;i++){ if((*L).elem[i]<100) printf("%2d ",i); else if( (*L).elem[i] <1000) printf("%3d ",i);} printf("\n——————————————————————\n"); printf("数据 | "); for(i=1;i<=(*L).length;i++)//格式对齐采用不同精度{ if((*L).elem[i]<100) printf("%2d ",(*L).elem[i]); else if( (*L).elem[i] <1000) printf("%3d ",(*L).elem[i]);} printf("\n"); return OK;}——————————顺序表主函数(测试)————————————void main(){ int cur_e; int pre_e; int next_e; int e; int i; sqList myl; /*测试函数*/ sqList *L = &myl;//申请指针空间 InitList(L);//创建线性表 creatlist(L);//测试输入 ListTraverse(L);//输出查看 /*前驱函数*/ printf("\n\n请输入表内数据,系统将会找出其的前驱:\n"); scanf("%d",&cur_e); pre_e = priorelem(L,cur_e,pre_e);if(pre_e != FALSE) printf("--%d的前驱是:%d--",cur_e,pre_e); /*后继函数*/ printf("\n\n请输入表内数据,系统将会找出其的后继:\n"); scanf("%d",&cur_e); next_e = nextelem(L,cur_e,next_e);if(next_e != FALSE) printf("--%d的后继是:%d--",cur_e,next_e); /*表长函数*/ ListLength(L); /*查找元素输出位序函数*/ printf("\n\n请输入你要查找的元素位序:\n"); scanf("%d",&i); e = GetElem(L,i,e);if(e == 0) printf("\n\n--线性表中不包含该位序,查找失败--\n");else printf("\n--线性表位序%d处的元素为:%d--\n",i,e); /*定位元素位序函数*/ printf("\n\n请输入你要查找的元素,系统将返回它的位序:\n"); scanf("%d",&e); i = LocateELem(L,i,e); if(i == 0) printf("\n\n--线性表中找不到该元素,查找失败--\n"); else printf("\n\n该元素的位序为:%d\n",i); /*插入函数*/ printf("\n\n请输如你要插入的数据和该数据插入的位置:\n"); scanf("%d%d",&e,&i); ListInsert_sq(L,i,e); ListTraverse(L); /*删除函数*/ printf("\n\n请输入你要删除的位序:\n"); scanf("%d",&i); e = ListDelete_sq(L,i,e);if(e != -1) printf("\n\n--位序%d的元素:%d已被删除--\n",i,e); ListTraverse(L);}
二.链式存储
内容:此线性表采用链式存储,实现了初始化、建表、查找、删除、打印,清空,销毁,返回前去后继等功能。
DAT *InitList(DAT *head)//创建空表{head = (DAT *)malloc(LEN);if(!head){printf("\n--链表创建失败--\n");exit(FALSE);}head ->next = NULL;return head;}DAT *creatList(DAT *head)//数据录入{DAT *p1,*p2;char ch;int n = 1;head = (DAT *)malloc(LEN);p1 = p2 = (DAT *)malloc(LEN);if(p1 != NULL){ printf("\n请输入数据:\n"); scanf("%d",&p1->data);//p1每一次存储都需要申请空间 head -> next = p1;//注意:本程序的头结点不存储数据 //p2 = p1;为什么这步可以省略呢?就是因为p1,p2在申请空间的时候被赋予的地址是一致的!printf("\n继续录入(y/any other keys to exit)?\n");getchar();scanf("%c",&ch);while(ch == 'Y'||ch == 'y'){printf("\n请输入数据:\n");p1 = (DAT *)malloc(LEN);if(p1 != NULL) scanf("%d",&p1->data);p2 -> next = p1;p2 = p1;printf("\n继续录入(y/any other keys to exit)?\n");getchar(); scanf("%c",&ch);}p2 -> next = NULL;//p2作为连接新建节点的指针,如果next为空,那自然是结束了录入printf("\n--录入结束--\n");}return head;} int ClearList(DAT *head) //保留头结点,其余节点数据清空 { if(head == NULL) { printf("\n--表不存在--\n"); return FALSE; } DAT *p,*q; p = head -> next; while(p) { q=p->next;//用声明的另一个指针q来记录p的下一节点的位置 printf("\n--已删除表中数据:%d--\n",p -> data); free(p); p=q;//结合q = p -> next,此语句的作用即是让p往后移动,从而实现逐个清空数据的目的 }//直至p为空的时候便是结束了循环,清空结束 head -> next = NULL; //数据清空之后头结点的指针域为空 return TRUE; } DAT *destroyList(DAT *head)//销毁 { if(head == NULL) { printf("\n--表不存在,销毁无效--\n"); exit(FALSE); } DAT *p; p = head; while(head) { p = head -> next; free(head);//第一次循环的时候清除了头结点 head = p; } printf("\n--链表销毁结束--\n"); return head; } int ListLength(DAT *head){DAT *p;int i = 0;p = head -> next;while(p){i++;p = p -> next;} printf("\n--链表长度为:%d--\n",i);return i;}void ListTraverse(DAT *head)//输出函数{DAT *p = head -> next;DAT *q = p;//位序输出遍历需要int n = 0;int length;length = ListLength(head);if(p){printf("\n位序 | ");for(n = 1;n <= length;n++){ if(q -> data <10) printf("%d ",n); else if(q -> data <100) printf("%2d ",n); else printf("%3d ",n); q = q -> next;}printf("\n------------------------------------\n");printf("数据 | ");do{printf("%d ",p -> data);p = p -> next;}while(p);}printf("\n");}int GetElem(DAT *head,int i,int e){ int n = 1; DAT *p; p = head ->next; while(p && n < i )//当p不为空且初始位序小于查找位序的时候 { p = p -> next;//指针后移直至与查找位序相等为止推出循环 n++; } if(!p || n > i) {printf("\n--找不到该位序--\n");return FALSE;} e = p -> data; return e;}int LocateElem(DAT *head,int e)//查找e的位序,并将其位序返回{DAT *p;int i = 1;printf("\n请输入你要查找的数据:\n");scanf("%d",&e); p = head -> next;while(p){ if(p -> data == e){printf("\n--%d的位序为:%d--\n",e,i);return i;}elsep = p -> next;i++;}printf("\n--找不到该元素--\n");return 0;}int PirrorElem(DAT *head,int cur_e,int pre_e)//查找元素的前驱{printf("\n请输入表中数据,系统将会返回其的前驱:\n");scanf("%d",&cur_e);if(head == NULL){printf("\n--表不存在--\n");return FALSE;}DAT *p,*q;q = head -> next;//q指向第一个节点 while(p) { p = q -> next;//p指向q的下一节点 if( q -> data == cur_e)//cur_e为第一个元素的时候,提示错误{printf("\n--表中第一个元素是没有前驱的,无法查找--\n"); return FALSE;} if(p -> data == cur_e)//如果p指针找到了cur_e,就用q返回前驱{pre_e = q -> data;printf("\n--%d的前驱是:%d--\n",cur_e,pre_e);return pre_e;}else{if( p -> next != NULL)q = p;//p,q指针相连,q后移也会带动p的后移else// p遍历结束达到NULL的时候即是没有找到输入的数据,提示错误{printf("\n--表中无此数据--\n"); return FALSE;}} }}int NextElem(DAT *head,int cur_e,int next_e)//查找元素的后继{DAT *p,*q;printf("\n请输入数据,系统将会返回其的后继:\n");scanf("%d",&cur_e);p = head -> next;while(p){q = p -> next;if( p -> data == cur_e && p -> next != NULL)//p没有下一节点的话,也就没有后继之说了{next_e = q -> data;printf("\n-%d的后继为:%d--\n",cur_e,next_e);return next_e;}if( p -> data != cur_e){p = q;//p -> next 不为空的时候,p,q后移遍历if( p -> next == NULL && p -> data == cur_e )//判断是否有后继{printf("\n--末位数据无法查找后继--\n");return FALSE;}if( p -> next == NULL && p ->data != cur_e)//判断时候存在cur_e{printf("\n--表中不存在该元素--\n");return FALSE;}}}}DAT *ListInsert(DAT *head,int i,int e)//按位序i插入特定元素e//定义结构体指针函数,用于返回结构体指针head{printf("\n请输入插入的位序和元素\n");scanf("%d%d",&i,&e);DAT *p = head;//和下面n = 0相对应,head无数据DAT *q;int n = 0;while(p != NULL && n < i-1)//找到i的前一个节点{p = p -> next;//循环第一次的时候p便指向了第一个节点,和n=1对应n++;//n = 1}//出循环时n=i-1,p也就指向了i的前一位序if(p == NULL || n > i-1)//i过大(插入的位序的前一个如果还是空的话,那就超出了插入范围)或过小的时候报错,退出{printf("\n--位序错误,插入失败--\n");return head;} q = (DAT *)malloc(LEN);//新节点空间申请q -> data = e;//新节点赋值q -> next = p->next;//新节点定位(p -> next为第i个节点),将新节点与原表中第i个节点相连,即是替换了第i的位置//如果是表尾插入的话,q -> next == NULLp -> next = q;//再将新节点与前面的p节点相连,即完成了插入printf("\n--%d已添加到表中第%d位序--\n",e,i);return head;//返回头指针,方便打印链表}DAT *ListInsert_last(DAT *head,int e)//表尾插入函数//定义结构体指针函数,用于返回结构体指针head{int leng = ListLength(head);DAT *p = head;//和下面n = 0相对应,head无数据DAT *q;int n = 0;while(p != NULL && n < leng)//找到尾节点,在尾节点的后一节点添加数据{p = p -> next;//循环第一次的时候p便指向了第一个节点,和n=1对应n++;//n = 1}//出循环时n=leng,p也就指向了表尾if(p == NULL || n > leng)//i过大(插入的位序的前一个如果还是空的话,那就超出了插入范围)或过小的时候报错,退出{printf("\n--位序错误,插入失败--\n");return head;} q = (DAT *)malloc(LEN);//新节点空间申请q -> data = e;//新节点赋值q -> next = p->next;//新节点定位(p -> next为第i个节点),将新节点与原表中第i个节点相连,即是替换了第i的位置//如果是表尾插入的话,q -> next == NULLp -> next = q;//再将新节点与前面的p节点相连,即完成了插入printf("\n--%d已添加到表尾--\n",e);return head;//返回头指针,方便打印链表}DAT *ListDelete(DAT *head,int i,int e){printf("\n请输入你要删除的位序:\n");scanf("%d",&i); DAT *p = head;DAT *q;int n = 0;while(p -> next != NULL && n < i - 1)//循环是为了找到要删除的节点的前驱,即p指向删除节点的上一个节点{p = p -> next;n++;}if(p -> next == NULL || n > i -1)//i过大或过小的时候报错退出(要删除的节点不能为空){printf("\n--位序错误,删除失败--\n");return head;}q = p -> next;//q指向p的下一节点p -> next = q -> next;//将p的下一节点绕到q的下一节点上去,完成对q节点的孤立,将q节点删除e = q -> data;//用e返回被删除的节点上的数据free(q);printf("\n--表中第%d位序上的数据:%d已被删除--\n",i,e);return head;}—————————单向链表主函数——————————void main(){ DAT *L1,*L2;int i,e;int cur_e;int pre_e;int next_e;//开始测试函数L1 = InitList(L1);//创建空表L2 = InitList(L2);//L1 = ListInsert(L1,i,e);L1 = creatList(L1);//输入数据ListTraverse(L1);L2 = creatList(L2);ListTraverse(L2); //ListTraverse(L1);//输出数据ListLength(L1);//输出链表长度//ClearList(L1);//清空数据//ListTraverse(L1);//输出清空效果 //destroyList(L1);//ListTraverse(L1);//查找位序上的元素数据 /*printf("\n请输入你要查找的位序:\n");scanf("%d",&i);e = GetElem(L1,i,e);if(e != FALSE) printf("\n--位序%d上的数据为:%d--\n",i,e);*///返回前驱//PirrorElem(L1,cur_e,pre_e);//返回后继//NextElem(L1,cur_e,next_e);//按位序插入新数据//L1 = ListInsert(L1,i,e);//按位序删除数据//L1 = ListDelete(L1,i,e);//表尾插入函数(拓展,方便进行合并链表的操作)/*printf("\n请输入要你在表尾插入的数据:\n");scanf("%d",&e);L1 = ListInsert_last(L1,e);ListTraverse(L1);*///用自建函数合并两个不同数据的链表 MergerLinks(L1,L2);//后面再做说明}
三.单向链表基本函数的运用,合并链表(未排序)
void MergerLinks(DAT *L1,DAT *L2){ DAT *L3 = NULL;DAT *p1 = NULL;DAT *p2 = NULL;DAT *p3 = NULL;DAT *p4 = NULL;DAT *p5 = NULL;int n = 0;int m = 0;int leng1;int leng2;int leng3;int i = 0,j = 0,k = 0;p1 = L1;p2 = L2;leng1 = ListLength(L1);leng2 = ListLength(L2);//链表长度获取L3 = (DAT *)malloc(sizeof(DAT));//第三链表的建立,用于存储表一和表二中不重复的数据p3 = p4 = (DAT *)malloc(sizeof(DAT));if(leng1 >= leng2){for(i = 0;i < leng2;i++){if(p2 -> next != NULL){p2 = p2 -> next;}for(j = 0; j < leng1;j++){ if(p1 -> next != NULL){ p1 = p1 -> next; }else//p1 -> next ==NULL的时候{p1 = L1 -> next;//重置p1回到L1的第一个节点}if(p2 -> data != p1 -> data)//表三数据链表的录入{ printf("\n--%d--\n",p2->data); printf("\n-|%d|-\n",p1->data); m++; printf("\nm = %d\n",m);if(m == leng1)//将表二的一个数对比表一中所有的数,如果都不一样则将这个数插入表三{ p3 -> data = p2 -> data;if(p3 -> data != NULL){ n++; if(n == 1) L3 -> next = p3; else p4 -> next = p3; p4 = p3; p3 =(DAT*)malloc (sizeof(DAT)); }p4 -> next = NULL;m = 0;//重置m}}}if(m <leng1)//m小于leng1说明有数重复,为了下一个数的比较可以顺利进行,标志m也要重置 m=0;} if(n==0)//结束查找,L3表中没有一个数据(n=0)L3 -> next = NULL; if(L3 -> next != NULL){ printf("\n待插入的数据如下:\n"); ListTraverse(L3); p5 = L3 -> next; for(k = 0;k < n;k++)//n即为表三的长度 { if(p5 -> data != NULL) { leng1 = leng1 +1; L1 = ListInsert_last(L1,p5 -> data);//调用表尾插入函数 } p5 = p5 -> next; }}printf("\n--合并之后的链表如下:--\n"); ListTraverse(L1);} else//leng1 < leng1的情况 {for(i = 0;i < leng1;i++){if(p1 -> next != NULL) {p1 = p1 -> next;}for(j = 0; j < leng2;j++){ if(p2 -> next != NULL) { p2 = p2 -> next;} else{p2 = L2 -> next;}if(p1 -> data != p2 -> data)//表三数据链表的录入{m++;if(m == leng2)//将表二的一个数对比表一中所有的数,如果都不一样则将这个数插入表三{ p3 -> data = p1 -> data;if(p3 -> data != NULL){ n++; if(n == 1) L3 -> next = p3; else p4 -> next = p3; p4 = p3; p3 = (DAT*)malloc (sizeof(DAT));}p4 -> next = NULL;m = 0;//重置m}}}if(m<leng2) m=0;} if(n==0)L3 -> next = NULL;if(L3 -> next != NULL){ ListTraverse(L3); p5 = L3 -> next; for(k = 0;k < n;k++)//n即为表三的长度 { if(p5 -> data != NULL) { leng2 = leng2 +1; L2 = ListInsert_last(L2,p5 -> data); } p5 = p5 -> next; }} printf("\n--合并之后的链表如下:--\n"); ListTraverse(L2); }}
- 线性表的存储以及相关操作实现
- 线性表的顺序存储实现及相关操作 C语言版
- 线性表的顺序存储实现及相关操作 C语言版
- 线性表的链式存储及相关操作 C语言版
- 线性表的链式存储及相关操作
- 【线性表】顺序存储、链式存储的实现及操作
- 线性表的相关操作
- 线性表的相关操作
- 线性表顺序存储的各项操作的实现
- (四)线性表的顺序实现及相关操作
- 线性表的顺序存储及操作实现
- python实现线性表顺序存储的插入操作
- 顺序存储操作的实现和线性表及其应用
- 线性表的顺序存储及操作实现
- python实现线性表顺序存储的插入操作
- 图的邻接表存储以及相关操作 C语言
- 【一】线性表以及线性表的顺序存储结构
- list 线性链表的相关操作。
- 无痛不快,无苦何甜,活着,本就是一种修行。
- Library Cache Lookup
- 最优秀的5个Linux文本编辑器
- 连接列值
- 昔日的教育界的霸主,今天能否成功转型?新东方未来的路在何方?
- 线性表的存储以及相关操作实现
- informix对某表上某个字段不能创建唯一性索引也不能删除索引 错误State:S0011
- RHEL / Centos 6: Install Nginx Using Yum Command
- Oracle中的正则替换【REGEXP_REPLACE】和正则like【REGEXP_like】
- Jcrop是一个功能强大的图像裁剪引擎
- powershell 杀掉子进程
- javascript,汉字转unicode|unicode转汉字
- RHEL/CentOS/Scientific Linux 6
- Spring配置中transactionAttributes的使用方法和作用