带头结点和不带头结点的单链表的尾插法以及各种操作

 

一.带头结点的单链表

先说一下create()建立的链表,采用cycle的方式。

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

带头结点的单链表13-1-1ex3.cpp

1.建立单链表

2.求链表长度

3.在第i个位置插入元素(种方法)

4.删除指定序号的节点

由于本程序是带头节点的,所以在删除函数Del()和插入函数InsertList()

中,head均没有被改变,所以,主函数中,用了Del和InsertList之后

均没有改变head,在PrintList中,还可以继续把head传入。如果是这样

的话,这两个函数完全可以定义成void类型,而不是Node *类型的

只要将Create()定义成Node *就行,再在main()中定义一个指针head

将head=Create();以后这个head都不会变了。好像带头节点链表的这些

常规操作均不改变Head节点。

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

#include

#include

//#include

//#include

 

typedef struct student

{

         int data;

         struct student *next;

         //struct student *pre;

}Node;

 

 

int GetLength(Node *head)

{

         int n=0;

         Node *p;

         p=head->next;

         while(p!=NULL)

         {

                  p=p->next;

                  n++;

         }

         return n;

}

 

Node *InsertList(Node *head, int x, int i) //插入元素方法1

{

         Node *p, *q, *s;

         int j=1;

         p=head;

         if(i<1 || i>GetLength(head)+1)

         {

                  exit(1);

         }

         s=(Node *)malloc(sizeof(Node));

         s->data=x;

         while(j<=i)

         {

                  q=p;

                  p=p->next;

                  j++;

         }

         s->next=q->next;

         q->next=s;

         return head;

}

 

void  InsertList2(Node *head, int x, int i) //插入元素方法2

{

         Node *p,*s;

         int j=1;

         p=head;

         if(i<1 || i>GetLength(head)+1) //这块儿比删除节点函数多加了一个,因为可以插入到最后一个节点的后面一个节点。但是删除节点函数不行,只能删除到最后一个节点

         {

                  exit(1);

         }

         s=(Node *)malloc(sizeof(Node));

         s->data=x;

         while(jnext;

                  j++;

         }

         s->next=p->next;

         p->next=s;

         //return head;

}

Node *Del(Node *head, int i)

{

         Node *p, *q;

         int j=1;

         p=head;

         if(i<1 || i>GetLength(head))

         {

                  exit(1);

         }

         while(jnext;

                  j++;

         }

         q=p->next;

         p->next=q->next;

         free(q);

         return head;

}

 

Node *create()

{

         Node *head, *p, *s;

         int x, cycle=1;

         head=(Node *)malloc(sizeof(Node));

         p=head; //如果换成带头节点的链表。这里也不能变,切记,不能变成p=head->next;那就错了

         printf("\nplease input the data:\n");

         while(cycle)

         {

                  //printf("\nplease input the data:\n");

                  scanf("%d",&x);

                  if(x!=0)

                  {

                          s=(Node *)malloc(sizeof(Node));

                          s->data=x;

                          //printf("\n %d", s->data);

                          p->next=s;

                          //s->pre=p;

                          p=s;

                  }

                  else

                  {

                          cycle=0;

                  }

         }

         p->next=NULL;

         //head=head->next;//注意,这句是不带头结点的单链表必须做的,因为按照算法。输入的第一个数实际上是赋值给了head->next

         //printf("\nhead->data:%d\n",head->data);

         return head;

}

 

void PrintList(Node *head) //打印链表的所有元素

{

         Node *p;

         p=head->next; //1)

         while(p!=NULL)

         {

                  printf("%3d", p->data);

                  p=p->next;

         }

         printf("\n");

}

 

int main()

{

         Node *p, *q ,*t, *head;

         head=create();

         //p=p->next;//如果是带头节点的单链表建立,除了少了上面那个函数的末尾的步之外,多了这一步,保证从head的下一个节点输出链表data。

         printf("\nnow output the linklist:\n");

         PrintList(head);

        

         InsertList2(head, 99,3);

         //q=q->next;

         printf("\nnow output the new linklist after INSERT:\n");

         PrintList(head);

         /*

         while(q!=NULL)

         {

                  printf("%3d",q->data);

                  q=q->next;

         }

         printf("\n");

         */

         

         Del(head, 3);

         printf("\nnow output the new linklist after DELETE:\n");

         PrintList(head);

         /*

         t=t->next;

         while(t!=NULL);

         {

                  printf("%3d",t->data);

                  t=t->next;

         }

         printf("\n");

         */

         system("pause");

         return 0;

}


 

运行结果如下:

1.输入为1 2 3 4 5 6。在第三个位置上插入一个数99,然后删除第3个节点(0为结束控制符)

2.输入为1 2。在第3个位置上,插入一个数99,然后删除第三个节点(0为结束控制符)

 

再说一下create2()建立的链表,采用传统的getchar()方式。

如果用create2()来建立,也很简单。create2()函数可以直接加在这个程序里面,另外再改动不多的几个地方就行,也就是把输入类型和PrintList中的输出类型改为char以及%c就行了,途中黄色高亮部分标记的就是要改的。

下面看一下create2()代码:

Node *create2()

{

         DataType x;

         Node *head=(Node *)malloc(sizeof(Node));

         Node *s, *r;

         r=head;

         while((x=getchar())!='\n') //注意,这个可是getchar()字符输入的。必须按照顺序输入,不能按空格也不能按回车,不然都会被当做一个字符

         {                                                                                     //getchar()把空格也当成一个字符,这点与scanf不同。比如输入:abcdefg回车。不能这样输入:a b c d e f g回车。

                  s=(Node *)malloc(sizeof(Node));

                  s->data=x;

                  r->next=s;

                  r=s; //r始终指向尾部节点

         }

         r->next=NULL;

         return head;

}


 

这么看来,2种方法都不错。

还有一点注意就是在插入的时候插入的是字符。别忘了加一个’ ‘。InsertList2(head, 'u',3);

运行结果:

1.      输入abcdefg

2.      输入1234567

 

 

二.不带头结点的单链表

说明:基本操作一样,只不过有些差别。

1.      在Create()中的p->next=NULL;之后,加一句head=head->next;也就是将头指针head后移。

2.      在PrintList()中,就没有p=head->next;了直接就p=head;了。

3.      在InsertList()中,需要分3中情况讨论:

a)       所插入的位置是首节点(head所指结点);

b)       所插入的位置是中间结点;

c)        所插入的位置是尾节点。

4.      在Del()中,需要分2种情况讨论:

a)       所插入位置是首节点(head所指结点);

b)       所插入位置是其他节点(中间节点或者尾节点)。

你可能感兴趣的:(C/C++,Java,数据结构与算法分析)