(C语言)单链表实验

265 阅读6分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1.(1):编写程序建立一个单链表,并逐个输出单链表中所有数据元素。

实现代码:

 #include <stdio.h>
 #include <stdlib.h>
 typedef struct node{
     int data;
     struct node *next;
 }linklist;
 linklist *CreateLinklist(){
     linklist *head,*p,*s;
     head = (linklist *)malloc(sizeof(linklist));
     p = head;
     printf("请输入单链表中的数据元素(输入-1时不做处理,输入结束):\n");
     int x;
     scanf("%d",&x);
     while (x != -1){
         s = (linklist *)malloc(sizeof(linklist));
         s->data = x;
         p->next = s;
         p = s;
         scanf("%d",&x);
     }
     p->next = NULL;
     return head; 
 }
 void PrintLinklist(linklist *head){
     linklist *t = head->next;
     if (t == NULL){
         printf("该单链表为空表!\n");
     }
     while(t != NULL){
         printf("%d ",t->data);
         t = t->next;
     }
 }
 int main(){
     linklist *l = CreateLinklist();
     printf("单链表中的所有元素为:");
     PrintLinklist(l);
     return 0;
 }

运行结果: 在这里插入图片描述

分析:

该程序中用于输出带头结点单链表中所有元素的函数的时间复杂度与空间复杂度均为线性阶O(n)。

(2):在递增有序的单链表中插入一个新结点x,保持单链表的有序性。 解题思路:首先查找插入的位置然后进行插入操作;从第一个结点开始找到第一个大于该新结点值的结点即为插入位置;然后在找到的此结点之前插入新结点;注意保留插入位置之前结点的指针才能完成插入操作。

实现代码:

 #include <stdio.h>
 #include <stdlib.h>
 typedef struct node{
     int data;
     struct node *next;
 }linklist;
 linklist *CreateLinklist(){
     linklist *head,*p,*s;
     head = (linklist *)malloc(sizeof(linklist));
     p = head;
     printf("请输入单链表中的数据元素(输入-1时不做处理,输入结束):\n");
     int x;
     scanf("%d",&x);
     while (x != -1){
         s = (linklist *)malloc(sizeof(linklist));
         s->data = x;
         p->next = s;
         p = s;
         scanf("%d",&x);
     }
     p->next = NULL;
     return head; 
 }
 void PrintLinklist(linklist *head){
     linklist *t = head->next;
     if (t == NULL){
         printf("该单链表为空表!\n");
     }
     while(t != NULL){
         printf("%d ",t->data);
         t = t->next;
     }
 }
 void SearchAndInsert(linklist *head,int x){
     linklist *p,*q;
     p = (linklist *)malloc(sizeof(linklist));
     p->data = x;
     if (head->next == NULL || head->next->data > x){ 
         p->next = head->next;
         head->next = p;
         return;
     }
     q = (linklist *)malloc(sizeof(linklist));
     q = head->next;
     while (q != NULL && q->next != NULL){
         if (x >= q->data && x < q->next->data){
             p->next = q->next;
             q->next = p;
             return;
         }
         q = q->next;
     }
     q->next = p;
     p->next = NULL;
 }
 int main(){
     linklist *l = CreateLinklist();
     printf("单链表中的所有元素为:");
     PrintLinklist(l);
     printf("\n请输入想要插入的新结点的数据域:");
     int x;
     scanf("%d",&x);
     printf("插入一个新结点后,单链表中的所有元素为:");
     SearchAndInsert(l,x);
     PrintLinklist(l);
     return 0;
 }

运行结果: 在这里插入图片描述

分析:

该程序中用于按照解题思路进行插入的SearchAndInsert函数的时间复杂度与空间复杂度均为线性阶O(n)。

(3):编写实现带头结点单链表就地逆置的子函数,并编写主函数测试结果。

这里先说一下我是如何实现逆置的: (方法并不唯一,如果有好的方法欢迎补充)

        基本思想是依照次序每次将一个结点放到头结点的后面。
        如输入单链表中的元素为345670,即:
        原始单链表为:head->3->4->5->6->7->0->NULL,则:
        第一次循环后,单链表变成:head->4->3->5->6->7->0->NULL
        第二次循环后,单链表变成:head->5->4->3->6->7->0->NULL
        第三次循环后,单链表变成:head->6->5->4->3->7->0->NULL 
        第四次循环后,单链表变成:head->7->6->5->4->3->0->NULL 
        第五次循环后,单链表变成:head->0->7->6->5->4->3->NULL
        综上,成功实现逆置。 

实现代码:

 #include <stdio.h>
 #include <stdlib.h>
 typedef struct node{
     int data;
     struct node *next;
 }linklist;
 linklist *CreateLinklist(){
     linklist *head,*p,*s;
     head = (linklist *)malloc(sizeof(linklist));
     p = head;
     printf("请输入单链表中的数据元素(输入-1时不做处理,输入结束):\n");
     int x;
     scanf("%d",&x);
     while (x != -1){
         s = (linklist *)malloc(sizeof(linklist));
         s->data = x;
         p->next = s;
         p = s;
         scanf("%d",&x);
     }
     p->next = NULL;
     return head; 
 }
 void PrintLinklist(linklist *head){
     linklist *t = head->next;
     if (t == NULL){
         printf("该单链表为空表!\n");
     }
     while(t != NULL){
         printf("%d ",t->data);
         t = t->next;
     }
 } 
 void ReverseLinklist(linklist *head){
     linklist *p,*q;
     p = head->next;
     if (p == NULL){
         return;
     }
     q = p->next;
     while (p->next != NULL) {
         p->next = q->next;
         q->next = head->next;
         head->next = q;
         do{
             q = q->next;
         }while(q != p->next);
     }
 }
 int main(){
     linklist *l = CreateLinklist();
     printf("逆置之前,单链表中的所有元素为:");
     PrintLinklist(l);
     printf("\n逆置之后,单链表中的所有元素为:");
     ReverseLinklist(l);
     PrintLinklist(l);
     return 0;
 }
 ​

运行结果: 在这里插入图片描述

分析:

该程序中带头结点单链表就地逆置子函数的时间复杂度为平方阶O(n²),空间复杂度为线性阶O(n)。

2.已知指针LA和LB分别指向两个无头结点单链表的首元结点。要求编一算法实现,从表LA中删除自第i个元素起共len个元素后,将它们插入到表LB中第j个元素之前。

实现代码:

 #include <stdio.h>
 #include <stdlib.h>
 typedef struct node{
     int data;
     struct node *next;
 }linklist;
 linklist *CreateLinklist(){
     linklist *head,*p,*s;
     head = (linklist *)malloc(sizeof(linklist));
     p = head;
     printf("请输入单链表中的数据元素(输入-1时不做处理,输入结束):\n");
     int x;
     scanf("%d",&x);
     if (x != -1){
         p->data = x;
     }else{
         p = NULL;
         return head;
     }
     scanf("%d",&x);
     while (x != -1){
         s = (linklist *)malloc(sizeof(linklist));
         s->data = x;
         p->next = s;
         p = s;
         scanf("%d",&x);
     }
     p->next = NULL;
     return head; 
 }
 void PrintLinklist(linklist *head){
     linklist *t = head;
     if (t == NULL){
         printf("该单链表为空表!\n");
     }
     while(t != NULL){
         printf("%d ",t->data);
         t = t->next;
     }
 }
 linklist *Get(linklist *head,int i){
     int j = 1;
     linklist *p = head;
     while ((p->next != NULL)&&(j < i)){
         p = p->next;
         j++;
     }
     if (j == i){
         return p;
     }else{
         return NULL;
     }
 }
 linklist *DeleteAndInsert(linklist *LA,linklist *LB,int i,int j,int len){
     linklist *p = LA,*q = LB,*m = NULL,*r = NULL,*s = NULL,*t = NULL;
     if (i <= 0 || j <= 0 || len <= 0){
         printf("无法进行删除和插入!");
         return NULL;
     }
     m = Get(p,i-1);
     if (m != NULL){
         while (len > 0){
             s = m->next;
             m->next = s->next;
             free(s);
             len--;
         }
     }else{
         printf("单链表LA中的第i个结点不存在!");
         return NULL; 
     }
     while (m->next != NULL){
         m = m->next;
     }
     t = Get(q,j-1);
     if (t != NULL){
         m->next = t->next;
         t->next = LA;
     }else{
         printf("单链表LB中的第j个结点不存在!");
         return NULL; 
     }
     return LB;
 }
 int main(){
     int i,j,len;
     printf("创建单链表LA\n");
     linklist *LA = CreateLinklist();
     printf("创建单链表LB\n");
     linklist *LB = CreateLinklist();
     printf("单链表LA中的所有元素为:");
     PrintLinklist(LA); 
     printf("\n单链表LB中的所有元素为:");
     PrintLinklist(LB); 
     printf("\n请输入i,j和len的值:\n");
     scanf("%d %d %d",&i,&j,&len);
     printf("从单链表LA中删除自第%d个元素起共%d个元素,插入到单链表LB中第%d个元素之前。",i,len,j);
     LB = DeleteAndInsert(LA,LB,i,j,len);
     printf("\n删除和插入操作完成之后,单链表LB中的所有元素为:");
     PrintLinklist(LB); 
     return 0;
 }

运行结果: 在这里插入图片描述 分析:

该程序中用于获得指向无头结点单链表中第i个结点的指针的函数的时间复杂度与空间复杂度均为线性阶O(n)。该程序中用于完成删除和插入操作的函数的时间复杂度为线性阶O(n),假设单链表LA和单链表LB中均有n个元素,则该函数的空间复杂度为线性阶O(n)。