#include<iostream>
using namespace std;
#define node struct student
#define null 0
#define len sizeof(struct student)
struct student
{
long num;
float score;
struct student *next;
};
int n;
struct student *creat()
{
struct student *p1,*p2,*head;//声明好数据结构体之后,就要为它们创建数据链表的函数
n=0;//用它来表示有几个这样的数据结构体
p1=p2=(struct student*)malloc(len);//为初始的该数据结果类型变量,动态分配改好合适的内存空间
cin>>p1->num>>p1->score;//内存中的空间以分配好,可以输入数据了
head=null;//初始头指针应该是空的
while(p1->num!=0)//与输入的某个数为零来停止不再输入
{
n=n+1;//一个整体的数已经建立就加一,它是全局变量
if(n==1)head=p1;//是第一数就把作为头指针,指针之间可直接通过变量赋值,它们都是指针即表示地址
else p2->next=p1;//前面都有节点,那么就加入前节点的后节点上
p2=p1;//p2是作为中间节点的指针变量来交换的
p1=(struct student*)malloc(len);//因为还要输入数据得在分配数据空间
cin>>p1->num>>p1->score;
}
p2->next=null;//最后的节点要记得指向空节点
return(head);
}
struct student *del(struct student *head,long num)//删除数据的函数
{
struct student *p1,*p2;
node *pc;
if(head==null)//考虑到健壮性或链表为空的情况处理
{
cout<<"list null!";
goto end;
}
p1=head;//不是空链表,就把传进来的链表头指针交给中间指针变量
while(num!=p1->num&&p1->next!=null)//判断是否存在要删除的数
{
p2=p1;//不是先暂时记录当前是节点
p1=p1->next;//之后就是指向下一个节点
}
if(num==p1->num)//如果是要删除的数,则有如下的操作
{
if(p1==head)head=p1->next;//要是删除的数是头结点,那么得把头结点的下一个节点作为头结点
else p2->next=p1->next;//不是头结点就把它的下一节点作为它上一节点的下一个数据节点
n=n-1;//节点是数减一
cout<<"delete data is:"<<num<<endl;
}
else cout<<"not been found!/t"<<num<<endl;
end:
return(head);//操作结束返回头节点
}
/*删除数据的函数是通过删除节点所实现的,首先要删除节点必须把链表的数据作为参数传
进来,同时要删除的数也作为参数传进来。首先判断待删除的数的链表是否为空,“0”或
“null”表示空,不为空是,判断要删除的数据是否一致,不一样,数据指向下一节点,找
到要删除的数时,用p2表示待删除节点的前一节点,再把待删除节点的下一节点地址赋给
p2节点的下一节点,为此达到了删除待删除节点的目的。*/
void print(struct student *head)
{
struct student *p;
p=head;
cout<<"These records are:"<<endl;
while(p!=null)
{
cout<<p->num<<'/t'<<p->score<<'/n';
p=p->next;
}
}
struct student *insert(struct student *head,struct student *pn)//声明链表数据的头指针参数,及插入数据的节点指针参数
{
node *pc,*pa;//声明两个结构节点指针变量,用于对插入数据的作为中间节点的转换
pc=pa=head; //首先初始化用于叫换的指针,把链表头指针赋与两指针。
if(head==0) //如果链表是空的,有如下的操作
{
head=pn; //将待插入的数据放入头指针
pn->next=0; //同时下一个节点的指针要为空
return head; //插入完数据,返回头节点指针
}
if(pn->score>=head->score)//如果插入的数据大于或等于头指针的数据,那么有如下操作
{
pn->next=head; //待插入的节点设置为头节点的上节点,即直接把头节点指针赋给该插入节点下一个数据指针
head=pn; //而此刻待插入数据的节点指针正是头结点指针,所以直接把该节点指针赋给头结点即可
return head;//插入操作完毕,返回头节点指针
}
while(pc->next!=0&&pn->score<=pc->score)//当待插入的节点数据小于或等于与头节点数据(或存在的数据),
{ //并且头结点的下一个节点不是空的,有如下操作
pa=pc; //先把当前比较的节点数据指针赋给中间转换的指针变量pa
pc=pc->next;//之后下一个节点作为当前要比较的节点,这里的下一个节点都是通过地址即指针来实现的
}
if(pn->score<=pc->score)//知道比较完所以链表中的数据,没有找到比要插入节点数据小时,则只能插入到最后
{
pc->next=pn;//把要插入的节点放到链表的最后一个节点的下一节点,作为新的最后一个节点
pn->next=0;//同时不要忘了最后节点的下一节点要指向空,表示数据的结束
}
else
{ pn->next=pc;//除了比头结点的数据和上面比较的小于比较节点数据小之外,剩下的就是大与与它(插入的数)比较的数,如此就插入给数之前
pa->next=pn;//该插入的节点作为之前还没插入节点时的前一节点的下一节点,因为链表的插入要表明前后节点之间的指向地址关系
}
return head;//最后插入操作完成之后当然是要返回链表的头结点了
}
int main()//在各函数模块都写好之后,编写主函数来对它们运用或测试也很重要,下面说明主函数如何编写调用它们
{
struct student *head,*stu;//声明这两个数据指针,是由于后面的操作所需
long del_num;//声明将要插入某数的变量
cout<<"please input number's and score's data:"<<endl;//提示输入数据的操作
head=creat();//建立数据链表,并把它的头指针的交给上面声明的头指针变量
print(head);//直接用头指针变量作为参数调用输出函数
cout<<"please input the delete number:"<<endl;//提示输入要删除的数据
cin>>del_num;//输入要删除的数据
while(del_num!=0)//输入零作为停止删除数据
{
head=del(head,del_num);//调用删除函数,完成操作新是数据头指针赋给声明的头指针变量
print(head);//对取进行验证
cout<<"please input the delete number:"<<endl;
cin>>del_num;
}
cout<<"input the inserted record:"<<endl;
stu=(struct student*)malloc(len);//因为要插入数据,所以得为插入的数据分配给一定的空间大小,此为类型、随机分配函数、大小的意思
cin>>stu->num>>stu->score;//虽然已经给输入的数据分配好空间了,但是它还没和链表中是数据形成一条连,所以要要通过指针来连接起来
while(stu->num!=0)//与输入的学好为零作为输入终止判断
{
head=insert(head,stu);//把此数据结构的节点传入到插入函数中,让其一链表连接在一起
print(head);//输出函数验证之
cout<<"input the inserted record:"<<endl;//以下语句决定是否还有插入数据
stu=(struct student*)malloc(len);
cin>>stu->num>>stu->score;
}
system("pause");
return 0;
}