单链表的基本操作

单链表的基本操作

一、实验目的:

1、复习C语言程序设计中的知识。

2、掌握线性表的链式存储结构的表示和实现方法。

3、掌握单链表基本操作的算法实现。

二、实验内容:

1.建立单链表。

2.在单链表上实现插入、删除和查找等操作。

三、实验要求:

编写实现单链表基本操作的以下函数,并在此基础上设计一个主程序完成如下功能:

初始化单链表L,类型自选;

⑵用头插法建立单链表L;

⑶用尾插法建立单链表L;

⑷输出单链表L的长度;

⑸输出单链表L的第i个元素(按位置查找);

⑹输出给定元素的位置(按内容查找);

⑺在第i个元素前插入给定元素(在第i个位置插入);

删除单链表L的第i个元素;

输出单链表;

⑽清空单链表(只保留头结点);

⑾菜单函数;

⑿单链表逆置;

建立一个非递减排序的单链表。

四、实验设计:

单链表的存储结构

typedef struct Node      //结点类型定义

{  ElemType  data;

  struct Node *next;

} *LinkList,Node;    // LinkList为单链表的类型名

实现顺序表所需的函数共涉及12个函数:

main() : 主函数

menu() : 菜单函数

InitList() :初始化函数

Create_LinkListF() :头插法建立单链表

Create_LinkListR() :尾插法建立单链表

LinkList_Length() :求单链表长度函数

GetData_LinkList() :单链表的位置查找函数

Search_LinkList() :单链表的内容查找函数

InsList() :单链表的的插入函数

DeleteNo_LinkList() :单链表的的指定位置结点删除函数

Print_LinkList() :单链表的遍历函数

SetNull_LinkList() :单链表的清空函数

单链表的函数描述

(1)函数名:main() 

输入:输入你选择的菜单编码,最后输入两个getchar()用于清除缓存区

输出:主函数调用菜单函数后输入菜单编码,调用相应的功能函数,每调完一个后按任意键就又返回主菜单,继续调用其他函数,当输出编码错误是输出“输入1~9之间的数字”,当所有功能完成后输出“程序结束”

算法描述:在while循环语句中,首先调用menu()函数,再用switch ()语句通过menu()函数中相应编码执行后面功能函数的调用,每执行一个功能函数后就跳出switch ()语句,继续输入其他的编码执行其他相应函数,一直到实现完所有的功能函数,最后如果输入编码错误是输出“输入1~9之间的数字”,另外,在switch ()语句中还要执行将1赋值给quit,如果当quit=1是就结束while循环语句,最后每调完一个功能函数后就输出“按任意键返回主菜单!”以及当所有功能完成后输出“程序结束”

(2)函数名:menu() 

输入:无

输出:首先输出每个编码所代表的功能函数的作用,再输出“输入需要访问的编号”

算法描述:把编码与功能函数一一对应

(3)函数名:InitList()

输入:无

输出:成功初始化就输出“初始化成功”

算法描述:首先定义一个单链表,之后在堆区申请分配一块指定大小的内存空间来存放单链表L,如果申请分配内存空间成功,就让单链表的头指针指向空指针,并且输出“初始化成功”

(4)函数名:Create_LinkListF() 

输入:输入你所建立单链表的元素

输出:首先输出输入的提示语句,建表完成后输出“头插法建立成功”

算法描述:首先定义单链表L,Node指针变量p,单链表元素的类型,再输入单链表的元素,之后用while循环语句,在循环体中,先在堆区申请分配一块指定大小的内存空间来存放节点p,然后把第一个元素赋值给p节点的数据域,再让p节点的指针指向原来头指针L指向的节点,最后再将原来头指针L指向p节点,当输入“#”时跳出while循环语句,建表完成后输出“头插法建立成功”,最后返回单链表

(5)函数名:Create_LinkListR()

输入:输入你所建立单链表的元素

输出:首先输出输入的提示语句,建表完成后输出“尾插法建立成功”

算法描述:首先定义单链表L,Node指针变量p和tail,单链表元素的类型,让头节点等于尾节点,再输入单链表的元素,之后用while循环语句,在循环体中,先在堆区申请分配一块指定大小的内存空间来存放节点p,然后把第一个元素赋值给p节点的数据域,再让尾节点的指针指向p节点,再让p节点指向尾节点,最后尾节点的指针指向空指针,当输入“#”时跳出while循环语句,建表完成后输出“尾插法建立成功”,最后返回单链表

(6)函数名:LinkList_Length()

输入:无

输出:输出单链表的长度

算法描述:首先定义单链表L,Node指针变量p,整形变量j,让p指向指向头节点,再用while循环语句,当p->next存在,p一直指向p的下一个节点,p每移动一次,j加1,直到p->next不存在时跳出while循环语句,最终输出单链表的长度

(7)函数名:GetData_LinkList()

输入:输入单链表查找的序号

输出:首先输出输入单链表查找的序号的提示语句,如果输入的数字不在顺序表范围之内就输出“访问位置不合理”或者“访问为空”,如果访问位置正确就输出取出的元素

算法描述:首先定义单链表L,Node指针变量p,整形变量i,j,输入单链表查找的序号,如果输入的数字不在顺序表范围之内就输出“访问位置不合理”,如果输入的数字在顺序表范围之内,首先让头节点指向p节点,再用while循环语句,当p->next存在同时j<i时,p一直指向p的下一个节点,p每移动一次,j加1,直到p->next不存在或者j>i时跳出while循环语句,如果i=j,就输出查找的元素,如果就j>i,就输出“访问为空”

(8)函数名:Search_LinkList()

输入:输入单链表查找的内容

输出:首先输出输入单链表查找的内容的提示语句,最后输出内容在单链表中的位置

算法描述:首先定义单链表L,Node指针变量p,整形变量j,元素的类型,输入你要在单链表中查找的元素,让p指向首元节点,再用while循环语句,当p存在时,如果p的数据域不等于查找的元素,就让p一直指向p的下一个节点,p每移动一次,j加1,直到p不存在时跳出while循环语句,最后输出查找元素的位置

(9)函数名:InsList()  

输入:输入插入位置和元素

输出:首先输出输入插入位置和元素的提示语句,当插入的数字不在顺序表范围之内就输出“插入错误”,如果当前位置pre为空, 表示已找完还未数到第i个,就输出“插入位置不合理!”,当成功插入就输出“插入成功”

算法描述:先定义单链表L,Node指针变量pre,s,整形变量i,k,元素的类型,输入插入的位置和元素,当插入的数字不在顺序表范围之内就输出“插入错误”,让pre指向头节点,再用while循环语句,如果pre不为空同时k小于输入位置的前一个元素,就让pre一直指向pre的下一个节点,pre每移动一次,k加1,如果pre为空,就输出“插入位置不合理!”,在堆区申请分配一块指定大小的内存空间来存放节点s,把输入的元素赋值给s的数据域,再让s节点的指针指向原来pre指向的节点,最后再将pre指向s节点,当成功插入就输出“插入成功”

(10)函数名:DeleteNo_LinkList()

输入:输入删除的位置

输出:首先输出输入删除的位置的提示语句,如果p->next=NULL就输出删除结点的位置i不合理!当成功删除就输出“删除成功”

算法描述:先定义单链表L,Node指针变量p,r,整形变量i,输入删除的位置

,让p指向头节点,再用while循环语句,如果p->next不为空同时k小于输入位置的前一个元素,就让p一直指向p的下一个节点,p每移动一次,k加1,如果p为空,就输出“删除结点的位置i不合理!”,r指向p节点,p指向p的下下一个节点,当成功删除就输出“删除成功”

(11)函数名:Print_LinkList()

输入:无

输出:首先输出单链表的遍历的提示语句,再输出单链表的遍历

算法描述:先定义单链表L,Node指针变量p,让p指向首元节点,再用while循环语句,如果p不为空,就依次输出每个元素,并让p指向p的下一个节点

(12)函数名:SetNull_LinkList() 

输入:无

输出:输出成功清空单链表

算法描述:首先单链表L,Node指针变量p,再用while循环语句,如果p存在,就让p指向头节点,L指向L的下一个节点,释放p,当全部清空就输出“成功清空单链表!”,并返回单链表

五、实验总结

  1. 在运行第6个按内容查找的时候,刚开始输入元素后,按回车键无法正常输出,检查代码也完全没问题,就卡在这一直进行不下去,最后想到可能是受空白字符的影响,如果没有加的话在我们输入第一个字符并以空格结束输入后,该字符与’\n’会一起进入标准流输入,’\n’便会作为第二个scanf语句的内容输入,从而让你的程序出现问题。 而加空格便会屏蔽空白字符。最后在输入控制符前加了一个空格后成功输出。
  2. 在运行第8个删除单链表中的指定位置的元素时,刚开始运用的时老师的代码,函数中有三个参数,但最终一直没能实现出来,最后改为两个参数,稍微改动了一些,最终成功实现。

六、代码实现

1、单链表的基本操作
#include<stdio.h>
#include<malloc.h>
#include <cstdlib>
typedef char ElemType;
typedef struct Node      //结点类型定义 
{  ElemType  data; 
  struct Node *next;
} *LinkList,Node;    // LinkList为单链表的类型名
void menu()
{
	system("cls");
	printf("***---1单链表的初始化---***\n");
	printf("***---2头插法单链表的建立和遍历---***\n");
	printf("***---3尾插法单链表的建立和遍历---***\n");
	printf("***---4单链表的长度---***\n");
	printf("***---5单链表按位置查找---***\n");
	printf("***---6单链表按内容查找---***\n");
	printf("***---7在单链表的第i个元素前插入指定元素---***\n");
	printf("***---8删除单链表中的第i个元素---***\n");
	printf("***---9单链表的遍历---***\n");
	printf("***---10单链表的清空---***\n"); 
	printf("***---11退出程序---***\n");
	printf("***---请输入需要访问的编号是(1~10)---***\n");
   }   
LinkList  InitList(LinkList  L)
{   L=(Node *) malloc (sizeof(Node));
    L->next=NULL;
    printf("初始化成功\n");
}
LinkList  Create_LinkListF()//头插法建立带头结点的单链表函数
{	ElemType  x;
	LinkList  L;
    Node *p;
	printf("请输入数据直到输入#结束:\n");
	scanf("%c", &x);							
	while (x != '#')					
    {p = (LinkList) malloc( sizeof(Node ) );	 
	p->data = x;					
	p->next = L->next;			
	L->next = p;					
	scanf("%c", &x); 					
	}
	printf("头插法建立成功!\n");
	return( L ); 
}
LinkList  Create_LinkListR( ) //尾插法	
{	ElemType  x;
	LinkList  L;
    Node *p, *tail;
	tail = L; 						
	printf("请输入数据直到输入#结束:\n");
	scanf("%c", &x);						
	while (x != '#')							
	{	p = (Node *) malloc( sizeof( Node ) );
		p->data = x;							
		tail->next = p;						
		tail = p;							
		tail->next = NULL;						
		scanf("%c", &x); 
	}
	printf("尾插法建立成功!\n");
	return( L ); 					
}
int LinkList_Length (LinkList  L)
{	Node  *p = L; //p指向头结点
	int  j = 0;
	while( p->next)
	{	p=p->next; 	//所指的是第j个结点
		j ++;
	}
	printf("输出单链表的长度:%d\n",j);
}
//按序号查找 
Node  *GetData_LinkList(LinkList L, int i)
{	Node  *p; 	
    int  j = 0;
    printf("请输入单链表查找的序号:");
	scanf("%d",&i); 
	if (i <= 0)		
    printf("访问位置不合理\n");	
	p = L;
	while( p->next && j < i )	
	{	p = p->next;
		j ++;
	}
	if ( i == j)    
	printf("%c\n",p->data);	//找到第i个节点
	else	
	printf("访问为空\n");
}
//按内容查找
int Search_LinkList(LinkList  L, ElemType  key)
{	Node *p;int j =0;
    printf("请输入单链表查找的内容:");
    scanf(" %c",&key) ;
	p = L->next;	
	while( p!=NULL&&p->data != key )
	{p = p->next;
	 j++;
	}
	if(p)
    printf("输出查找内容的位置:%d\n",j);
}
//在带头结点的单链表L中第i个位置插入值为e的新结点 
void InsList(LinkList L, int i, ElemType e)
{     Node *pre, *s; 
      printf("输入插入的位置和元素:"); 
	  scanf("%d %c",&i,&e); 
      int k; 
      if(i<=0)  
	  printf("插入错误!\n");
      pre=L;   k=0; 
      while(pre!=NULL&&k<i-1)  
//在第i个元素之前插入, 则先找到第i-1个数据元素的存储位置, 使指针pre指向它  
     {pre=pre->next; 
        k=k+1; 
      } 
     if(! pre)      
//如果当前位置pre为空, 表示已找完还未数到第i个,所以一定是插入位置不合理所致 
    printf("插入位置不合理!\n");
      s=(Node*)malloc(sizeof(Node));    //为e申请一个新的结点并由s指向它 
      s->data=e;                        //将待插入结点的值e赋给s的数据域  
      s->next=pre->next;                //完成插入操作 
      pre->next=s;  
      printf("插入成功!\n");
} 
int  DeleteNo_LinkList(LinkList L, int i)
/* 在带头结点的单链表L中删除第i个元素, 并将删除的元素保存到变量*e中 */ 
{  printf("输入删除的元素的位置:"); 
   scanf("%d",&i); 
    Node *p, *r; 
    int k; 
    p=L; k=0; 
    while(p->next!=NULL&&k<i-1)    
	/* 寻找被删除结点i的前驱结点i-1使p指向它 */
   {p=p->next;                       
	k=k+1;
   } 
 if(k!=i-1)     /* 即while循环是因为p->next=NULL而跳出的 */ 
 {
    printf("删除结点的位置i不合理!\n"); 
    return 0;  
 }
 r=p->next; 
 p->next=p->next->next;      /* 删除结点r */
 printf("删除成功!\n");
} 

void Print_LinkList( LinkList  L)
{	Node  *p = L->next;
    printf("单链表的遍历:"); 
	while(p != NULL)
	{printf(" %c ", p->data); 			          
	p = p->next;	
	}
}
LinkList  SetNull_LinkList(LinkList L)
{   Node  *p; 
    while(p)
    {p=L;
     L=L->next;
     free(p);
	}
    printf("成功清空单链表!\n"); 
    return(L);	
}
int main()
{LinkList  L;int i,select,quit=0;ElemType key,e;
   while(1)
   {   menu();
	scanf("%d",&select);
	switch (select)
	{
	    case 1:L=InitList(L);break;
		case 2:L=Create_LinkListF();Print_LinkList(L);break;
	    case 3:L=Create_LinkListR();Print_LinkList(L);break;
		case 4:LinkList_Length(L);break;
		case 5:GetData_LinkList(L,i);break;
		case 6:Search_LinkList(L,key);break;
		case 7:InsList(L,5,e);break;
		case 8:DeleteNo_LinkList(L,7);break;
		case 9:Print_LinkList(L);break;
		case 10:SetNull_LinkList(L);break;
		case 11:quit=1;break;
		default:printf("输入1~10之间的数字\n");break;
	}
	    if(quit==1)
	    {
	    	break;
		}
		printf("按任意键返回主菜单!\n");
		getchar();
		getchar();
		printf("程序结束!\n");
	}
	return 0; 
}
3、单链表的应用
#include<stdio.h>
#include<malloc.h>
typedef char ElemType;
typedef struct Node      //结点类型定义 
{  ElemType  data; 
  struct Node *next;
} *LinkList,Node;    // LinkList为单链表的类型名
LinkList  InitList(LinkList  L)
{   L=(Node *) malloc (sizeof(Node));
    L->next=NULL;
    return L;
}
LinkList  Create_LinkListF()//头插法建立带头结点的单链表函数
{	ElemType  x;
	LinkList  L;
    Node *p;
	printf("请输入数据直到输入#结束:\n");
	scanf("%c", &x);							
	while (x != '#')					
    {p = (LinkList) malloc( sizeof(Node ) );	 
	p->data = x;					
	p->next = L->next;			
	L->next = p;					
	scanf("%c", &x); 					
	}
	return( L ); 
}
LinkList  Create_LinkListR() //尾插法	
{	ElemType  x;
	LinkList  L;
    Node *p, *tail;
	tail = L; 						
	printf("请输入数据直到输入#结束:\n");
	scanf("%c", &x);						
	while (x != '#')							
	{	p = (Node *) malloc( sizeof( Node ) );
		p->data = x;							
		tail->next = p;						
		tail = p;							
		tail->next = NULL;						
		scanf("%c", &x); 
	}
	return( L ); 					
}
void Print_LinkList( LinkList  L)
{	Node  *p = L->next;
	while(p != NULL)
	{printf(" %c ", p->data); 			          
	p = p->next;	
	}
}
int main()
{   LinkList  L; 
    L=Create_LinkListF();
	printf("单链表的逆置:"); 
	Print_LinkList(L);
	printf("\n"); 
    L= Create_LinkListR( );
    printf("单链表的升序建立:");
	Print_LinkList(L); 
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值