验证单链表及其上的基本操作

目录

目的

验证单链表及其上的基本操作

内容及要求

  1. 定义单链表类。
  2. 实验验证如下算法的正确性、各种功能及指标:
    1)创建单链表;
    2)插入操作:分别在当前结点后、表头、表尾插入值为x的结点;
    3)删除操作:分别删除表头结点、表尾结点和当前结点的后继结点;
    4)存取操作:分别存取当前结点的值和单链表中第k个结点的值;
    5)查找操作:查找值为x的元素在单链表中出现的位置(是链表中的第几个元素)。
  3. 为便于观察程序的运行结果,设计的输出函数能在屏幕上以规范、直观的形式输出计算结果。例如将链
    表输出成如下形式:[1]->[2]->[3]->[4]->[5]
  4. 测试程序时,对所有输入变量取遍各种有代表性的值。
  5. 为了增强程序的可读性,程序中要有适当的注释。

实验过程

算法设计、代码编写、程序调试、测试数据设计、测试

算法设计

先编写有关单链表操作的各个函数:
InitList(LinkList *&L);
DestroyList(LinkList *&L);
ListEmpty(LinkList *L);
ListLength(LinkList *L);
DispList(LinkList *L);
GetElem(LinkList *L,int i,ElemType &e);
LocateElem(LinkList *L,ElemType e);
ListInsert(LinkList *&L,int i,ElemType e);
ListDelete(LinkList *&L,int i,ElemType &e);
之后的五个函数对应主函数中的五项功能,通过选择结构语句确定执行哪项功能。

在这里插入图片描述

代码编写

#include <stdio.h> 
#include <malloc.h> 
typedef char ElemType; 
typedef struct LNode	/*定义单链表结点类型*/ 
    { 	
        ElemType data;
		struct LNode *next; 
		 } LinkList; 
		 
		void InitList(LinkList *&L) 
    { 	
		 L=(LinkList *)malloc(sizeof(LinkList)); 	/*创建头结点*/ 	
		 L->next=NULL; 
		 
		 }
		void DestroyList(LinkList *&L) 
	{ 	
	      LinkList *p=L,*q=p->next; 	
		while (q!=NULL) 	
		{ 		
		   free(p); 		
		   p=q; 		
		   q=p->next; 	
		   } 	
		   free(p); 
		   } 
		int ListEmpty(LinkList *L) 
    { 	
		  return(L->next==NULL); 
		  } 
		int ListLength(LinkList *L) 
	{ 	
	      LinkList *p=L;
		  int i=0; 	
		  while (p->next!=NULL) 	
		  { 		
		    i++; 		
		    p=p->next; 	} 	
			return(i); 
		} 
		void DispList(LinkList *L) 
	{ 	
	      LinkList *p=L->next;
		  while (p!=NULL) 	
		  { 		
		    printf("%c",p->data);
		    p=p->next; 	
			} 	
			printf("\n"); 
		} 
		int GetElem(LinkList *L,int i,ElemType &e)   //查找值 
	{ 	
	      int j=0; 	
		  LinkList *p=L; 	
		  while (j<i && p!=NULL) 	
		  { 		
		    j++; 		
			p=p->next; 	} 	
			if (p==NULL || i<1) // 当超出上界或者下界时,查询失败 	
			{ 		
			  printf("您输入的元素位置数据不合法!\n"); 		
			  return 0; 	
			  }else 	
			  { 		
			    e=p->data; 		
				return 1; 	
				} 
			} 
			int LocateElem(LinkList *L,ElemType e)    //查找位置 
		{ 
		     LinkList *p=L->next; 	
			 int n=1; 	
			 while (p!=NULL && p->data!=e) 	
			 { 		
			   p=p->next; 		
			   n++; 	
			   } 	
			 if (p==NULL) 		
			  return(0); 	
			 else 		
			  return(n); 
			  } 
			int ListInsert(LinkList *&L,int i,ElemType e)   //插入节点 
		{ 	  
		      int j=0; 	
			  LinkList *p=L,*s; 	
			while (j<i-1 && p!=NULL) 	
		    { 		
		      j++; 		
			  p=p->next; 	
			  } 	
			  if (p==NULL || i<=0)	/*未找到第i-1个结点*/ 	
			  { 		
			    printf("插入失败!\n"); 		
				return 0; 	
				}else			/*找到第i-1个结点*p*/ 	
				{ 	s=(LinkList *)malloc(sizeof(LinkList));	/*创建新结点*s*/ 		
				    s->data=e;								 		
					s->next=p->next;						/*将*s插入到*p之后*/ 		
					p->next=s; 		
					printf("插入完成!\n") ; 		
					return 1; 	
					  } 
			} 
			int ListDelete(LinkList *&L,int i,ElemType &e)    //删除节点 
		{ 	  int j=0; 	
		      LinkList *p=L,*q; 	
			  while (j<i-1 && p!=NULL) 	
			  { 		
			    j++; 		
				p=p->next; 	} 	
			  if (p==NULL || i <1 ||q==NULL )				/*未找到第i-1个结点*/ 	
			  { 		
			    return 0; 	
				}else						/*找到第i-1个结点*p*/ 	
				{ 	q=p->next; /*q指向要删除的结点*/ 
				    e=q->data; 		
					p->next=q->next;		/*从单链表中删除*q结点*/ 	 
					free(q);				/*释放*q结点*/ 	 
					return 1; 	} 
			} 
            
//             void InitList(LinkList *&L); 
//			   void DestroyList(LinkList *&L); 
//			   int ListEmpty(LinkList *L); 
//			   int ListLength(LinkList *L); 
//			   void DispList(LinkList *L); 
//			   int GetElem(LinkList *L,int i,ElemType &e); 
//			   int LocateElem(LinkList *L,ElemType e); 
//			   int ListInsert(LinkList *&L,int i,ElemType e); 
//			   int ListDelete(LinkList *&L,int i,ElemType &e); 

        int three(LinkList *h,int pos,ElemType &e){
        	Sur:printf("\n请输入你要查询的数据元素的位置(数字):"); 	
			   scanf("%d", &pos) ; 	
			   if(GetElem(h,pos,e)) 	
			   { 		
			     printf("单链表h的第%d个元素=%c\n", pos, e); 	
				 } 	else { 		
				     printf("查询失败!\n"); 
				SurEle:	printf("你是否要继续查询?(Y/N)") ; 		
					   getchar(); 
					   char ele;		
					   scanf("%c", &ele) ; 		
					   switch (ele)
					   { 		
					     case 'Y': 		
						 case 'y': goto Sur ; break; 		
						 case 'N': 		
						 case 'n': printf("您选择放弃再次查询!\n") ; break; 
						default: printf("您输入的数据不合法!请重新输入:\n"); goto SurEle ; break; 		
						} 	
						} 
		}
		int two(LinkList *h,ElemType e){
			SurCon:printf("\n请输入你要查找的数据元素的值:") ; 	
					   getchar(); 	
					   scanf("%c", &e) ; 	
					   if (LocateElem(h,e)) 	
					   { 		
					     printf("查找成功,元素%c的位置=%d\n", e, LocateElem(h,e)); 	
						 } 	else 	{ 		
						      printf("查询失败!你输入的数据元素的值不存在!\n") ; 
				SurConEle:	printf("你是否要继续查询?(Y/N)") ; 		
				            getchar(); 
							char ele;		
							scanf("%c", &ele) ; 		
							switch (ele) 		
							{ 		
							  case 'Y': 		
							  case 'y': goto SurCon ; break; 		
							  case 'N': 		
							  case 'n': printf("您选择放弃再次查询!\n") ; break; 
						default: printf("您输入的数据不合法!请重新输入:\n"); goto SurConEle ; break; 		
						    } 	
						} 	
		}
		int one(LinkList *h){
			printf("\n请输入你要插入的数据元素的位置和数据元素值(以逗号隔开):"); 
			int pos;
			ElemType e;
						scanf("%d,%c", &pos, &e); 	
						if (ListInsert(h, pos, e)) 	
						{ 			
						  printf("输出成功插入元素后的单链表h:"); 			
						  DispList(h); 	
						} 
		}
		int four(LinkList *h,int pos,ElemType &e){
				Dle:printf("\n请输入你要删除的数据元素的位置:"); 	
				     //getchar(); 	
					 scanf("%d", &pos) ; 	
					 if(ListDelete(h,pos,e)) 	
					 { 		
					   printf("删除成功!你删除的位置的数据元素值为%c\n", e) ; 		
					   printf("输出成功删除元素后单链表h:"); 		
					   DispList(h); 		
					   printf("你是否要继续删除?(Y/N)") ; 		
					   getchar(); 
					   char ele; 		
					   scanf("%c", &ele) ; 		
					   switch (ele) 		
					   { 		
					     case 'Y': 		
						 case 'y': goto Dle ; break; 		
						 case 'N': 		case 'n': printf("您选择不再继续删除!\n") ; break; 
						default: printf("您输入的数据不合法!请重新输入:\n"); goto Dle ; break; 		
						} 	
					} 	else 	
					   { 		
					     printf("删除失败!请检查你输入的数据元素的位置!\n") ; 
					DleEle:	printf("你是否要继续再次尝试删除?(Y/N)") ; 		
					        getchar(); 
							char ele;		
							scanf("%c", &ele) ; 		
							switch (ele) 		
							{ 		
							  case 'Y': 		
							  case 'y': goto Dle ; break; 		
							  case 'N': 		
							  case 'n': printf("您选择放弃尝试删除!\n") ; break; 
						default: printf("您输入的数据不合法!请重新输入\n"); goto DleEle ; break; 		
						} 	
						}
		}
		int five(LinkList *h){
			    printf("\n释放单链表h。。。\n"); 	
				DestroyList(h); 
				printf("\n释放单链表h成功!!\n");
				
		}
			int main() { 	
			   int pos; 	
			   LinkList *h; 	
			   ElemType e; 	
			   	
			   printf("(1)初始化单链表h\n"); 	
			   InitList(h); 	
//			   printf("\n(2)依次插入a,b,c元素\n"); 	
//			   ListInsert(h, 1, 'a'); 	
//			   ListInsert(h, 2, 'b'); 	
//			   ListInsert(h, 3, 'c'); 	
//			   printf("\n(3)输出单链表h:"); 	
//			   DispList(h); 	
//			   printf("\n(4)单链表h长度=%d\n",ListLength(h)); 	
//			   printf("\n(5)单链表h为%s\n",(ListEmpty(h)?"空":"非空")); 
			   
			   int choice;
	  while(1){
	  printf("\n\n1:插入元素\n2:查询元素的位置\n3:查询元素的值\n4:删除元素\n5:释放单链表\n");
	  scanf("%d",&choice);
	  switch(choice){
	  	case 1:one(h);break;
	  	case 2:two(h,e);break;
	  	case 3:three(h,pos,e);break;
	  	case 4:four(h,pos,e);break;
	  	case 5:five(h);break;
	  }
    }
			   
		return 0;		
			} 



程序调试

  1. 单链表的操作main.cpp [Error] ‘pos’ was not declared in this scope
    进行分析后发现错误是由于并未在函数中声明pos的类型,当把pos声明为int类型时,错误消失。
  2. 单链表的操作main.cpp [Error] too few arguments to function ‘int two(LinkList*, ElemType)’
    进行分析后发现错误是由于调用函数时传参不够,当把e传进去后,错误消失。

测试数据设计

先输入1,选择插入元素功能;然后输入1,a;在第一个节点插入a;
之后再输入2,b;在第一个节点后插入b;
再输入3,c;在第二个节点后插入c;
再输入2,选择查询元素位置功能;然后输入b;返回2;
再输入3,选择查询元素的值功能;然后输入1,返回a;
再输入4,选择删除元素功能;然后输入1,返回删除成功,输出b,c;
再输入5,选择释放单链表功能;返回释放成功。

结果

在这里插入图片描述
在这里插入图片描述

总结

  • 程序运行过程中有许多冗杂的地方,还有许多需要改进的地方。
  • 关于错误方面,构造存储结构时需要注意字母的大小写。还有遇到输入数据错误时应加上返回语句return 0,否则会出现程序检查时没有错误但运行时出现内存错误的提示。在函数调用时函数的形参不能写类型。
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值