C的日记-链表操作

 

【链表】

 包括:头指针变量、链表节点(普通变量+指针变量);
  头指针变量中存放第一个节点的内存地址,链表节点(结构体)中的指针变量中存放下一个节点的内存地址。

  head头指针变量是打开链表的钥匙!

【静态链表】

[建立]给链表中每个节点成员赋值,取第一个节点内存地址赋值给头指针变量,剩下依次赋值给前一个指针变量。
[输出]:获取头节点中地址,然后进行循环获取下一个节点数据和地址,赋值并输出,直到下个节点中指针为空。


【动态链表】


[建立]:
    <1>sizeof获取链表中节点(结构体)的成员所占字节数。
    <2>定义三个基类型为结构体的指针变量:struct student *head,*p1,*p2;head指针变量用于存储链表首节点的地址,p1指针变量用于在循环时获取动态内存的地址和判断是否结束以及未结束的赋值给p2;p2主要用来进行接受p1传来的非结束的地址和设定链表结束指针变量为0;


[输出]:
    已知:链表首节点的地址;
    循环活取当前节点中的指针变量成员所对应的节点的数制,直到当前指针变量值为0。


[删除]:
    分析:三种删除情况:删除表头节点、删除表中节点、删除表尾节点;
        表头节点:<1>更改head指针变量指向 <2>free释放原始表头节点
        表中节点:<1>更改要删除节点之前节点中指针变量使其指向之后节点地址 <2>释放当前节点空间
        表尾节点:<1>更改倒数第二个节点中的指针变量使其为0 <2>释放当前节点空间

先查询位置,根据位置执行操作

  struct node *delet(head,pstr)/*以head为头指针,删除pstr所在节点*/  

    struct node *head;  

    char *pstr;  

    {  

        struct node*temp,*p;  

        temp  = head;  /* 链表的头指针*/  

        if (head==NULL)/* 链表为空*/   

            printf("\nListis null!\n");  

        else /*非空表*/  

        {  

                    temp = head;  

            while (strcmp(temp->str,pstr)!=0 && temp->next!=NULL)/* 若节点的字符串与输入字符串不同,并且未到链表尾*/  

            {  

                p = temp;  

                temp = tmep->next;/* 跟踪链表的增长,即指针后移*/ //跳出循环时,temp存放当前的节点地址,p存放上一个节点地址

            }  

            if(strcmp(temp->str,pstr)==0) /*找到字符串*/  

            {  

              if(temp==head) { /* 表头节点*/  

                  printf("delete string :%s\n",temp->str);  

                  head = head->next;  

                  free(temp);/*释放被删节点*/  

              }  

              else  

              {  

                  p->next=temp->next; /*表中节点*/  

                  printf("delete string :%s\n",temp->str);  

                  free(temp);  

              }  

          }else {

              printf("\nno find string!\n");/*没找到要删除的字符串*/  

          }  

          return(head);  

      }  
  };


[插入]:
    分析:三种插入情况:插入到表头、插入到表中、插入到表尾;
        表头:<1>更改head指针变量使其指向新插入节点;<2>更改新插入节点中指针使其指向原始的第一个节点。
        表中:<1>更改要插入节点之前节点中指针变量使其指向当前节点;<2>使当前节点指向之后的节点。
        表尾:<1>更改倒数第二个节点中的指针变量使其指向当前节点;<2>使表尾节点中指针变量为0。

首先定义链表结构

struct{ int num; /*学生学号* / char str[20]; /*姓名*/ struct node *next; } ;

根据位置执行操作

struct node *insert(head,pstr,n) /*插入学号为n、姓名为p s t r 的节点*/

struct node *head; /*链表的头指针*/

char *pstr; 

int n;

{

    struct node *p1,*p2,*p3;

    p1=(struct node*)malloc(sizeof(struct node))/*分配一个新节点*/

    strcpy(p1->str,pstr); /*写入节点的姓名字串*/

    p1->num = n; /* 学号*/

    p2 = head;

    if(head==NULL) /* 空表*/

    {

        head=p1; 

        p1->next=NULL;/*新节点插入表头*/

    }

    else/*非空表*/

    { 

        while(n>p2->num&&p2->next!=NULL)

        /*输入的学号小于节点的学号,并且未到表尾*/

        {

            p3 = p2;

            p2 = p2->next;/* 跟踪链表增长*/ //跳出循环时,p3存放插入点前面的节点地址,p2存放插入点后面的点地址

        }                        

        if(n<=p2->num) { /*找到插入位置*/ 

            if(head==p2) /* 插入位置在表头*/

            {

                head = p1;

                p1->next = p2;

            }

            else

            { /*插入位置在表中*/

                p3->next = p1;

                p1->next = p2;

            }

        }else{ /*插入位置在表尾*/ //如果链表中有比插入的学号大的,必然查到头部/中间,但如果插入的是最大的,自然插入到表尾

            p2->next = p1;

            p1->next = NULL;

        }

    }

    return(head); /* 返回链表的头指针*/

}    

 

【实例】

创建包含学号、姓名节点的单链表。其节点数任意个,表以学号为序,低学号的在前,高学号的在后,以输入姓名为空作结束。在此链表中,要求删除一个给定姓名的节点,并插入一个给定学号和姓名的节点。

# include <stdlib.h>

# include <malloc.h>

struct node /*节点的数据结构*/

{

    int num;

    char str[20];

    struct node *next;

};

/* * * * * * * * * * * * * * * * * * * * * * * * * * * */

main( )

{

    /*函数声明*/

    struct node *creat();

    struct node *insert();

    struct node *delet();

    void print( );

    struct node *head;

    char str[20];

    int n;

    head=NULL; /*做空表*/

    head=creat(head); /*调用函数创建以head 为头的链表*/

    print(head);/*调用函数输出节点*/

    printf("\n input inserted num,name:\n");

    gets(str); /*输入学号*/

    n=atoi(str);

    gets(str); /*输入姓名*/

    head=insert(head, str, n); /*节点插入链表*/



    print(head);

    printf("\n input deleted name:\n");

    gets(str); /*输入被删姓名*/

    head=delet(head,str); /*用函数删除节点*/

    print(head); /*调用函数输出节点*/

    return;

}

/* * * * * * * * * * * * * * * * * * * * * */

/* * * 创建链表* * * * * * * * * * * */

struct node *creat(struct node *head)

{

    char temp[30];

    struct node *pl,*p2;

    pl=p2=(struct node*)malloc(sizeof(struct node));

    printf("input num, name: \n");

    printf("exit:double times Enter!\n");

    gets(temp);

    gets(pl->str);

    pl->num=atoi(temp);

    pl->next = NULL ;

    while(strlen(pl->str)>0)

    {

        if(head==NULL)//if the chain is null

             head= pl;//

        else 

            p2->next=pl;//set the p2->next NULL

        p2 = pl;//

    pl=(struct node*)malloc(sizeof(struct node));

    printf ("input num, name: \n");

    printf("exit:double times Enter!\n"); 

    gets(temp);

    gets(pl->str);

    pl->num=atoi(temp);

    pl->next= NULL; 

     }        

    return head;

}

/* * * * * * * * * * * * * * * * * * * */

/* * * * * * * * * * 插入节点* * * * * * * * * */

struct node *insert(head, pstr,n)

struct node *head;

char *pstr;

int n;

{

    struct node *pl,*p2,*p3;

    pl=(struct node*)malloc(sizeof(struct node));

    strcpy (pl->str, pstr);

    pl->num = n;

    p2 = head; 

    if(head == NULL)



    {

        head = pl; 

        pl->next = NULL;

    }

    else

    {

    while (n>p2->num&&p2->next!=NULL)

    {

        p3 = p2;

        p2= p2->next;

    }

    if (n<=p2->num)

    if (head==p2)

    {

        head = pl;

        pl->next = p2;

    }

    else

    {

        p3->next = pl;

        pl->next=  p2; 

    }

    else

    {

        p2->next= pl;

        pl->next = NULL;

    }

}

    return(head);

}

/* * * * * * * * * * * * * * * * * * * * * * * * */





/* * * * * 删除节点* * * * * * * * * * * * */

struct node *delet (head, pstr)

struct node *head;

char *pstr;

{

    struct node *temp,*p;

    temp =head;

    if (head==NULL)

    printf("\nList is null!\n");

    else

    {

        temp = head;

        while(strcmp(temp->str,pstr)!= 0 && temp->next!=NULL)

        {

            p = temp;

            temp= temp->next;

        }

        if(strcmp(temp->str,pstr)== 0)

        {

            if (temp== head)

            {

                head = head->next;

                free(temp);

            }

            else

            {

                p->next =temp->next;

                printf("delete string :%s\n",temp->str);

                free(temp);

            }

        }

        else 

            printf("\nno find string!\n");

    }

    return(head);

}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/* * * * * * * * * * 链表各节点的输出* * * * * * * * * */  

void print(struct node *head)

{

struct node *temp;

temp = head;

printf("\n output strings:\n");

while (temp!=NULL)

{

printf("\n%d-----%s\n",temp->num,temp->str);

temp= temp->next;

}

return;

} 
View Code

运行结果:

root@android-virtual-machine:/uniteq_smb/test# ./test1

input num, name: 

exit:double times Enter!

11

aa

input num, name: 

exit:double times Enter!

12

bb

input num, name: 

exit:double times Enter!







 output strings:



11-----aa



12-----bb



 input inserted num,name:

13

cc



 output strings:



11-----aa



12-----bb



13-----cc



 input deleted name:

aa



 output strings:



12-----bb



13-----cc

 

你可能感兴趣的:(链表)