数据结构学习二 数据结构之链表代码版【创建,遍历,删除,插入】

来源:互联网 发布:ipad玩游戏网络不稳定 编辑:程序博客网 时间:2024/04/29 12:28

代码:

/******动态链表的建立、删除、插入的完整程序*****/#include    "stdio.h"#include    "string.h"#include    "stdlib.h"#define Len sizeof(struct student)  //定义一个结构体等长的常量len,用于给新的结构体分配空间/*********************************    结构体名:student**********************************/struct student{    int num;    int score;    struct student *next;};//此分号容易忘记!!!struct student *head,*p1,*p2;//P1指向待插入节点,P2为首节点,head为头结点!int n=0;   //用于记录插入链表的个数/*********************************    函数名 :*creat()    参数   :无     功能   :用于插入新的链表    返回值 :返回链表的首地址 head    基本思路:  三个结点(头结点head、尾结点 NULL 和待插入结点 P)        第一步:定义头结点head、尾结点 p2 和待插入结点p1,待插入的结点数据部分初始化;        第二步:P1该结点被头结点、尾结点同时指向。        P1=p2=(struct student*)malloc(LEN);头指针部分为空,head=NULL;         第三步:重复申请待插入结点空间,对该结点的数据部分赋值(或输入值),将该结点插入在最前面,或者最后面(书上在尾部插入).            P2->next=P1;  P2=P1;          第四步:最后:P2->next=NULL;*********************************/struct student *creat(){    //第二步 P1该结点被头结点、尾结点同时指向。P1=p2=(struct student*)malloc(LEN);头指针部分为空,head=NULL;     head=NULL;    p1=(struct student*)malloc(Len);    //插入前先开辟一个空节点位置,给新的节点分配空间    p2=p1;//P1替换掉P2,包括指针域和数据域    //第一步 定义头结点head、尾结点 p2 和待插入结点p1,待插入的结点数据部分初始化;    puts("请输入学生号和成绩");    scanf("%d %d",&(p1->num),&(p1->score));    while(p1->num!=0)    {        n++;        if(n==1) head=p1;        else p2->next=p1;        p2=p1;          p1=(struct student*)malloc(Len);            printf("建立链表%d\n",n);        scanf("%d %d",&(p1->num),&(p1->score));    }    p2->next=NULL;    puts("链表建立结束");    return head;}/*******************************************    函数名 :print()    参数  :结构体的首地址 *head1    功能  :输出链表    返回值 : 无    基本思路:传入一个链表的头结点地址,遍历链表即可。            1.单向链表总是从头结点开始的;            2.每访问一个结点,就将当前指针向该结点的下一个结点移动:                p=p->next;            3.直至下一结点为空                P=NULL*******************************************/void print(struct student *head1){    struct student *p3;    p3=head1;    puts("输出链表");    puts("学号     成绩");    while(p3!=NULL)    {        printf("%d     %d\n",p3->num,p3->score);        p3=p3->next;    }}/*******************************************    函数名 :*del()    参数  :链表首地址 *head 以及要删除的学习             学号    功能  :把指定学号的学生信息从链表中    删除掉,    返回值 :返回链表的首地址head    基本思路:两种情况:            1、要删的结点是头指针所指的结点则直接操作;            2、不是头结点,要依次往下找。另外要考虑:空表和找不到要删除的结点********************************************/struct student *del(struct student *head ,int num){    struct student *sp1,*sp2;    if(head==NULL)  {printf("list is null!"); goto End;}    sp1=head;    while(num!=sp1->num)        //删除的不是所要找的结点    {           sp2=sp1;sp1=sp1->next;  //当节点中的学号不想等时移动指针sp1    }    if(num==sp1->num)    {        if(sp1==head)                  {            head=sp1->next;    //若sp1指向的是首结点,把第二个结点地址给head        }        else if(sp1->next==NULL)  /*若sp1指向的最后一个结点,把倒数第二个                                   sp2->next=NULL作为最后一个结点*/        {            sp2->next=NULL;        }        else         {            sp2->next=sp1->next;   //否则删除sp1所指的结点        }        n--;        printf("已删除%d",num);    }    else printf("找不到该节点\n");End :;    return head;}/********************************************    函数名 :*insert()    参数  :链表首地址*head 和要插入新结点            地址*newstu    功能    :在链表中再插入新的结点    返回值 :返回新的链表首地址head    基本思路:将一个结点插入到已有的链表中        插入原则:            1、插入操作不应破坏原链接关系            2、插入的结点应该在它该在的位置        实现方法:            应该有一个插入位置的查找子过程        共有三种情况:            1、插入的结最小            2、插入的结点最大            3、插入的结在中间            同删除一样,需要几个临时指针:            P0: 指向待插的结点;初始化:p0=数组stu;            P1: 指向要在P1之前插入结点;初始化: p1=head;            P2: 指向要在P2之后插入结点;            插入操作:当符合以下条件时:p0->num 与 p1->num 比较找位置            if(p0->num>p1->num)&&(p1->next!=NULL)  则插入的结点不在p1所指结点之前;指针后移,交给p2;             p1= p1->next;              p2=p1;            则继续与p0指向的数组去比,直到(p1->next!=NULL)为止。              否则有两种情况发生:                 if(head==p1) head=p0;p0->next=p1插到原来第一个结点之前;                    else p2->next=p0;p0->next=p1; 插到 p2 指向的结点之后;                还有另外一种情况:插到最后的结点之后;                p1->next=p0;p0->next=NULL;*********************************************/struct student *insert(struct student *head,                      struct student *newstu){   struct student *p0,*sp1,*sp2;   sp1=head;                     //使sp1指向第一个结点   p0=newstu;                   //使p0指向新结点的地址   if(head==NULL)               //原来的链表是空的   {       head=p0;       p0->next=NULL;              }   else   {       while(sp1->num<p0->num&&sp1->next!=NULL)       {           sp2=sp1;             //使sp2指向刚才sp1的结点,移动sp1指针到下一个结点           sp1=sp1->next;       }       if(p0->num<sp1->num)       {           if(head==sp1)                     {               head=p0;         //插入到原来第一个结点之前               p0->next=sp1;    //让新的结点指向第一个结点             }           else            {               sp2->next=p0;    //否则插入到sp2和sp1之间                p0->next=sp1;               }       }        n++;   }   return head;         //返回新的首地址;}void main(){    struct student *p,newstu;    int num;    puts("创建链表");    p=creat();           //创建链表    print(p);            //输出全部链表    puts("请输入要删除的学号");    scanf("%d",&num);    p=del(p,num);        // 删除链表    print(p);    puts("请输入插入学生的学号和成绩");    scanf("%d %d",&newstu.num,&newstu.score);    p=insert(p,&newstu);    //插入链表    print(p);    print(p);    free(p1);    free(p2);    free(head);}
0 0