[数据结构] 单向链表

数据结构之单项链表学习笔记
#include <stdio.h>
#include <stdlib.h>

struct link *AppendNode(struct link *head,FILE *fp);
struct link *DeleteNode(struct link *head, int nodeData);
struct link *InsertNode(struct link *head, int nodeData);
struct link *ReverseNode(struct link *head);
void CountNode(struct link* head);
void DeleteAll(struct link *head);
void SearchNode(struct link *head, int nodeData);
void DisplsyNode(struct link* head);
void DeleteMemory(struct link* head);

struct link
{
	int data;
	struct link *next;
};

因为方便及作业要求采用int型数据类型,数据采用文件读入链表,先在主函数里将升序数组读入文件,此处可加以修改,读者可自行考虑修改。
int main()
{
	int i = 0;
	int j;
    struct link* head = NULL; /* linked table head pointer*/ 
	
	FILE *fp;
	char filename[30];//文件名 
	int judge; 
	int nodeData;
	
	int str[3]={2,3,4};
	if((fp=fopen("linked table.txt","w"))==NULL)//判断文件是否成功打开 
	{
	     printf("Failure to open linked table.txt!\n") ;
	     exit(0);
	} 
    for(i=0;i<2;i++)
    {
    	fprintf(fp,"%d\n",str[i]);
    }
    fprintf(fp,"%d",str[i]);
	fclose(fp);
	//向文件中输入数据 
	
	printf("********************Linked Table*********************\n");
	printf("1.Create\n2.Delete\n3.Insert\n4.Search\n5.Display\n6.Delete All\n7.Count\n8.Reverse\n9.Free\n10.Exit\n"); 
	printf("********************Linked Table*********************\n");
	
	scanf("%d",&judge);
	while(judge!=1&&judge!=10)
	{
		printf("Have not created a linked table!\n");
		scanf("%d",&judge);
	}
	if(judge==10) 
	  exit(0);
	printf("Please Input the filename:\n");
	getchar();//读走回车 
	gets(filename);
	
	if((fp=fopen(filename,"r"))==NULL)//判断文件是否成功打开 
	{
	     printf("Failure to open linked table.txt!\n") ;
	     exit(0);
	} 
	
    for(j=0;!feof(fp);j++)//从文件中将数据读取到链表 
    {
    	head = AppendNode(head,fp);
    }
	 
	fclose(fp);
	printf("Create Successful!\n");
	DisplsyNode(head);//显示
	printf("********************Linked Table*********************\n");
	while(1)
	{
	    scanf("%d",&judge);
	    while(judge==1)
	    {
    		printf("Repetitive Operation!");
    		scanf("%d",&judge);
    	}
    	if(judge==10)
    	  exit(0);
	    if(judge==2)
	    {
    		printf("Delete nodeData:\n");
    		scanf("%d",&nodeData);
    		head = DeleteNode(head,nodeData);
    		DisplsyNode(head);//显示
    		printf("********************Linked Table*********************\n");
    	}
	    
	    if(judge==3)
	    {
    		printf("Insert nodeData:\n");
    		scanf("%d",&nodeData);
    		head = InsertNode(head,nodeData);
    		DisplsyNode(head);//显示
    		printf("********************Linked Table*********************\n");
    	}
    	if(judge==4)
    	{
	    	printf("Search nodeData:\n");
    		scanf("%d",&nodeData);
    		SearchNode(head,nodeData);
    		
    		printf("********************Linked Table*********************\n");
	    }
        if(judge==5)
          DisplsyNode(head);//显示
        if(judge==6)
		{
			DeleteAll(head);
			//DisplsyNode(head);//显示
			exit(0);
		}  
        if(judge==7)
        {
        	CountNode(head);
        	printf("********************Linked Table*********************\n");
        }
	    if(judge==8)
	    {
    		head=ReverseNode(head);
    		DisplsyNode(head);//显示
    	}	
	    if(judge==9)
		{
			DeleteMemory(head);
			exit(0);
		} 
	
	}
	DeleteMemory(head);
	return 0;
}
此处由界面判断具体操作注意文件名由键盘输入时会多一个\n,应由getchar()读走。
/*Set a new node and append it to the end of the linked table
return the head pointer of the new linked table.*/
struct link* AppendNode(struct link *head,FILE *fp)
{
	struct link *p=NULL, *pr =head;
	int data;
	
	p = (struct link*)malloc(sizeof(struct link));/*让p指向新节点*/
	if(p == NULL)//若为新建节点申请内存失败,则退出程序 
	{
		printf("No enough memory to allocate! \n");
		exit(0);
	} 
	if(head == NULL)//若原链表为空表 
	{
		head = p;//将新建节点置为头节点 
	}
	else
	{
		while (pr->next!=NULL)//若未到表尾,则移动pr直到pr指向表尾
		{
		   pr = pr->next;
		}
		pr->next = p;/*让末节点的指针域指向新建节点*/ 
	}
		
	//printf("Input node data:");
	fscanf(fp,"%d",&data);
	
	p->data = data;
	p->next = NULL;
	return head;//return head pointer. 
}
链表的创建函数,由文件读入
/*for display*/
void DisplsyNode(struct link* head)
{
	struct link *p = head;
	int j = 1;
	while (p != NULL)
	{
		printf("%5d%10d\n",j,p->data);//打印第J个点的数据
		p = p->next;
		j++; 
	}
}
链表的显示函数。注意j从1开始计。
void DeleteMemory(struct link *head)//释放内存 
{
	struct link *p=head, *pr = NULL;
	while(p!=NULL)//若不是表尾,则释放节点占用的内存
	{
	    pr = p;
		p = p->next;
		free(pr);
	}
	
}
链表的内存释放函数。
struct link *DeleteNode(struct link *head, int nodeData)
{
	struct link *p = head, *pr = head;
	if(head == NULL)//若链表为空表,则退出程序 
	{
		printf("Linked Table is empty!\n");
		return(head);
	}
	while(nodeData != p->data && p->next != NULL)//Not been found and no getting to the end;
	{
		pr = p;
		p=p->next;
	}
	
	if(nodeData == p->data) //若当前节点的节点值为nodeData,找到待删除节点
	{
	    if(p == head)//若待删除节点为头节点 
		{
		    head = p->next;	
		} 
		else
		{
			pr->next = p->next;//important:让前一节点的指针域指向待删节点的下一节点 
		}
		free(p); 
	}
	else
	{
		printf("This Node has not been found!\n");
	}
	return head;
}
链表的删除指定的节点数据。
struct link *InsertNode(struct link *head, int nodeData)
{
	struct link *pr = head, *p = head, *temp = NULL;
	p = (struct link*)malloc(sizeof(struct link));//让p指向待插入节点
	if(p == NULL)
	{
		printf("No enough memory!\n");
		exit(0);//退出程序 
	} 
	
	p->next=NULL;//为待插入节点的指针域赋值为空指针
	p->data=nodeData;//为待插入节点数据域赋值为nodeData 
	if(head == NULL)//若原链表为空表
	{
		head = p;
	} 
	else
	{
		while(pr->data < nodeData && pr->next != NULL)
		{
			temp = pr;
			pr = pr->next;
		}
		if(pr->data >= nodeData)
		{
			if(pr == head)//若在头节点前加入新节点
			{
			     p->next = head;
			     head = p;
			}
			else
			{
				pr = temp;
				p->next = pr->next;
				pr->next = p;//让前一节点的指针域指向新节点 
			}
		}
		else//表尾 
		{
			pr->next = p;//让末节点的指针域指向新节点 
		} 
	}
	return head;//return head pointer after inserting the new node of linked table. 
}
链表之插入指定数据函数,原链表以升序排序,此处给定数据进行比较以确定插入位置。
void SearchNode(struct link *head, int nodeData)
{
	struct link *p = head, *pr = head;
	int i=1;
	if(head == NULL)//若链表为空表,则退出程序 
	{
		printf("Linked Table is empty!\n");
		
	}
	while(nodeData != p->data && p->next != NULL)//Not been found and no getting to the end;
	{
		pr = p;
		p=p->next;
		i++;
	}
	if(nodeData == p->data) //若当前节点的节点值为nodeData
	{
		printf("%5d%10d\n",i,p->data);
	}

}
查找指定数据在链表中的位置。
void DeleteAll(struct link *head)
{
	struct link *p=head,*pr;
	if(head == NULL)//若链表为空表,则退出程序 
	{
		printf("Linked Table is empty!\n");
	}
	while(head!=NULL)
	{
            
			head = p->next;
			pr = p->next;
			free(p);
            p=pr;
            
    }
    printf("Delete All!\n");
   
}
删除整个链表,删除后头节点为空,显示出现垃圾数据,此处不予显示,待改进疑问
void CountNode(struct link* head)
{
	struct link *p = head;
	int j = 0;
	while (p != NULL)
	{
		//printf("%5d%10d\n",j,p->data);//打印第J个点的数据
		p = p->next;
		j++; 
	}
	printf("The Totai nodes are %d.\n",j);
}
计算链表长度,遍历链表,与显示函数差不多,直接拷贝。
struct link *ReverseNode(struct link *head)
{
	struct link *p1 = head, *p2 = head->next, *p3;
	if(head==NULL||head->next==NULL)  
    {  
        return head;  
    }
	while(p2!=NULL)
	{
		p3 = p2->next;  
        p2->next = p1;  
        p1 = p2;  
        p2 = p3;  
	}
	head->next = NULL;  
    return p1;     
}<span style="font-size:14px;">
</span>
反序输出链表,注意此处用三个指针进行轮换。
不足之处请诸君指教!!!


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值