数据结构之单项链表学习笔记
因为方便及作业要求采用int型数据类型,数据采用文件读入链表,先在主函数里将升序数组读入文件,此处可加以修改,读者可自行考虑修改。
不足之处请诸君指教!!!
#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>
反序输出链表,注意此处用三个指针进行轮换。
不足之处请诸君指教!!!