数据结构随笔

来源:互联网 发布:编辑软件图标 编辑:程序博客网 时间:2024/06/08 15:30

在前一段学习的数据结构中,我感觉对于链表的知识有些遗忘,其实终究看来是C语言知识的遗忘,下面我将借助以下几个详细的例子,来看看我们相关的的结构体指针与链表。其实在我看来,我一直感觉结构体是类的雏形,没有成型的类,备受限制而又非常开放的类。下面我们还是以链表为例:

单链表:

1)头指针变量head──指向链表的首结点。

2)每个结点由2个域组成:

              数据域──存储结点本身的信息。

              指针域──指向后继结点的指针。

3)尾结点的指针域置为“NULL(空)”,作为链表结束的标志。

对于数据的操作无外乎是由“增,删,改,查”四项功能来组合而成的,真有点像人与“衣,食,住,行”的关系。

对链表的基本操作

对链表的基本操作有:创建、遍历(查找)、插入、删除等。

1)创建链表是指,从无到有建立起链表,即往空链表中依次插入若干结点,并保持结点之间的前驱和后继关系。

2)遍历链表是指,查找链表上所有结点。

3)插入结点是指,在结点ki-1ki之间插入一个新的结点k’,使线性表的长度增1,且ki-1ki的逻辑关系发生如下变化:

插入前,ki-1ki的前驱,kiki-1的后继;插入后,新插入的结点k’成为ki-1的后继、ki的前驱。

4)删除结点是指,删除结点ki,使线性表的长度减1,且ki-1kiki+1之间的逻辑关系发生如下变化:

删除前,kiki+1的前驱、ki-1的后继;删除后,ki-1成为ki+1的前驱,ki+1成为ki-1的后继。

实例展示:

struct  node//创建结构体

   {

      char no[7];             /*学号*/

      int score;                /*成绩*/

      struct node  *next; /*指针域*/

    };

下面我们来创建一个新链表

基本思路:

首先向系统申请一个结点的空间,然后输入结点数据域的(2个)数据项,并将指针域置为空(链尾标志),最后将新结点插入到链表尾。对于链表的第一个结点,还要设置头指针变量。

另外,案例代码中的3个指针变量pheadpnewptail的说明如下:

1phead──头指针变量,指向链表的第一个结点,用作函数返回值。

2pnew──指向新申请的结点。

3ptail──指向链表的尾结点,用ptail->next=pnew,实现将新申请的结点,插入到链表尾,使之成为新的尾结点。

/*CreateTab()函数: 创建链表*/

/*形参:int n 结点的个数*/

/*返回值:返回链表的头指针*/

struct node*CreateTab( int n )

{   int i;  /*循环变量*/

    struct node *pnew, *phead=NULL, *ptail;

/*(1)phead──头指针变量,指向链表的第一个结点,用作函数返回值。

2pnew──指向新申请的结点。

3ptail──指向链表的尾结点*/

for(i=0;i<n;i++)  /*用循环建立n个结点,注意第3个表达式为空*/

 { 

  /*申请一个新结点的空间*/

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

  /*1、输入结点数据域的各数据项*/

        printf("Input the ID of studentNo.%d(6 bytes): ", i+1);

        scanf("%6s", pnew->ID);

        printf("Input the score of thestudent No.%d: ", i+1);

        scanf("%d",&pnew->score);

  /*2、置新结点的指针域为空*/

        pnew->next=NULL;

  /*3、将新结点插入到链表尾,并设置新的尾指针*/

        if(i==0)

            phead=pnew;  /*是第一个结点, 置头指针*/

        else

            ptail->next=pnew;       /*非首结点, 将新结点插入到链表尾*/

        ptail=pnew;                  /*设置新的尾结点*/

  }

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

}

/*遍历链表*/

voidFindTab(struct node *p)

{

    printf("List of Student'sID&Score/n");

   printf("=========================/n");

    printf("ID      Score/n");

    while(p!=NULL)

    {  printf("%s  %d/n",p->ID,p->score);

        p=p->next;

    }

}

  对链表的插入操作

编写一个insert()函数,完成在单链表的第i个结点后插入1个新结点的操作。当i=0时,表示新结点插入到第一个结点之前,成为链表新的首结点。

基本思路:

通过链表的头指针,首先找到链表的第一个结点;然后顺着结点的指针域找到第i个结点,最后将新结点插入到第i个结点之后。

/*函数功能:在单链表的第i个结点后插入1个新结点*/

/*函数参数:phead为链表的头指针,pnew指向要插入的新结点,i为结点索引号*/

/*函数返回值:链表的头指针*/

struct node*insert(struct node *phead, struct node *pnew, int i)

{ struct node*pointer;  /*将新结点插入到链表中*/

if(phead==NULL)   /*将新结点插入到1个空链表中*/

       phead=pnew, pnew->next=NULL;      

else  /*非空链表*/

       if(i==0) /*使新结点成为链表新的首结点*/

       pnew->next=phead,  phead=pnew;

       else  /*其他位置*/

          { pointer=phead;/*查找单链表的第i个结点(pointer指向它)*/

              for(;  pointer!=NULL && i>1;  pointer=pointer->next,  i--)  ;

                   if(pointer==NULL)              /*越界错*/

                        printf("Out of therange, can’t insert new node!/n");

                   else       /*一般情况:pointer指向第i个结点 */

              pnew->next=pointer->next,pointer->next=pnew;

            }

       return(phead);

}

对链表的删除操作

编写一个delete()函数,删除链表的指定结点。

基本思路:

通过链表的头指针,首先找到链表的结点;然后顺着结点的指针域找到第i个结点,最后将新结点插入到第i个结点之后。

/*函数功能:删除链表的某个结点*/

/*函数参数:phead为链表的头指针,pdel指向要删除的结点*/

/*函数返回值:若删除成功返回1,否则返回0*/

intdelete(struct node *phead, struct node *pdel)

{ struct node*temp;

if (phead==pdel)/*如果要删除的是头结点*/

       phead=phead->next; /*将头结点指向它的下一个结点*/  

else  /*如果不是删除头结点*/

    {     temp=phead;/*暂存头指针到temp*/

       while(temp->next != pdel)  /*查找要删除的结点*/

          { if(temp->next != NULL)

              temp=temp->next;

            else  return(0);/*如果没找到要删除的结点*/

          }

       temp->next=pdel->next;/*找到要删除的结点后*/

    }

    free(pdel);/*释放被删除结点的内存空间*/

    return(1);

}

原创粉丝点击