首页 > 其他分享 >顺序表和链表

顺序表和链表

时间:2023-11-03 23:33:29浏览次数:29  
标签:Linklist 结点 顺序 15 head next 链表

writeup后面写

258.链表去重

给定一个键值为整数的单链表 L, 将键值的绝对值有重复的结点删除: 即对任意键值 K, 只有键值或其绝对值等于 K 的第一个结点被保留在 L 中。

例如, 下面单链表 L 包含键值 21、-15、 15、 7、 -15, 如下图(a) 所示; 去重后的链表 L 包含键值 21、 -15、 7, 如下图(b)所示。

 

 

输入说明:

输入的第一行包含两个整数, 分别表示链表第一个结点的地址和结点个数 n(1≤n≤100)。 结点地址是一个非负的 5 位整数, NULL 指针用-1 表示。

随后 n 行, 每行含 3 个整数, 按下列格式给出一个结点的信息: Address Key Next

其中 Address 是结点的地址, Key 是绝对值不超过 10000 的整数, Next 是下一个结点的地址。

 

输出说明:

输出的第一行为去重后链表 L 的长度, 换行; 接下来按顺序输出 L 的所有结点, 每个结点占一行, 按照 Address Key Next 的格式输出, 间隔 1 个空格。

 

测试样例:

输入样例 1

00100 5

99999 7 87654

23854 -15 00000

87654 -15 -1

00000 15 99999

00100 21 23854

 

输出样例 1

3 0 0100 21 23854

23854 -15 99999

99999 7 -1

 1 /*
 2   问题描述:
 3   给定一个键值为整数的单链表 L, 将键值的绝对值有重复的结点删除: 
 4   即对任意键值 K, 只有键值或其绝对值等于 K 的第一个结点被保留在 L 中。 
 5   例如, 下面单链表 L 包含键值 21、-15、 15、 7、 -15, 去重后的链表 L 包含键值 21、 -15、 7
 6   
 7   输入说明:
 8   输入的第一行包含两个整数, 分别表示链表第一个结点的地址和结点个数 n(1≤n≤100)。 
 9   结点地址是一个非负的 5 位整数, NULL 指针用-1 表示。
10   随后 n 行, 每行含 3 个整数, 按下列格式给出一个结点的信息:
11   Address Key Next
12   其中 Address 是结点的地址, Key 是绝对值不超过 10000 的整数, Next 是下一个结点的地址。
13   
14   输出说明:
15   输出的第一行为去重后链表 L 的长度, 换行; 接下来按顺序输出 L 的所有结点, 每个结点
16   占一行, 按照 Address Key Next 的格式输出, 间隔 1 个空格
17   
18   测试样例:
19   输入样例 1
20   00100 5
21   99999 7 87654
22   23854 -15 00000
23   87654 -15 -1
24   00000 15 99999
25   00100 21 23854
26   输出样例 1
27   3 
28   00100 21 23854
29   23854 -15 99999
30   99999 7 -1
31   
32     参考了CSDN后考虑数组模拟链表的方法,也就是静态链表法,其实课本上也有,没注意看到,,,;静态链表法同样有基本操作的实现;可以看到整个代码的实现是非常简洁的
33  */
34 #include<stdio.h>
35 #include<stdlib.h>
36 #include<math.h>
37 
38 struct
39 {
40     int key;
41     int next;
42 }Initarr[100000];//建立数组结构体,结构体内存键值和下一个结点的地址,而数组下标用来代替首地址
43 
44 int first_address,i,n,finalarr[100000],repeat[100000];//建立两个数组,一个是输出的final数组,一个是判断重复键值的repeat数组
45 
46 int main()
47 {
48     int len=0;
49     scanf("%d %d",&first_address,&n);
50     for(i=0;i<n;i++)
51     {
52         int a,b,c;
53         scanf("%d %d %d",&a,&b,&c);
54         Initarr[a].key=b;
55         Initarr[a].next=c;//将三个量存进去,这里用数组模拟链表,也就是数组实现静态链表,其实访问数组某元素也是访问他的内存头地址,类似的道理
56         
57     }
58     for(i=first_address;i>-1;i=Initarr[i].next)//for循环实现一个连续的遍历,从first_addrest到Initarr[].next存的地址(数组下标)最后到-1终止
59     {
60         int key=abs(Initarr[i].key);//取绝对值
61         if(repeat[key]==0)//这里用0,1标识是否重复,由于比较的是相同key(取绝对值了),所以repeat数组下标用key来指定唯一位置
62         {
63             repeat[key]=1;
64             finalarr[len++]=i;//不重复就把首地址存到final数组中,输出用
65         }
66         //不满足条件的话就会继续循环,当然也可以把剔除的存到另一个数组,用else分支写
67     }
68     printf("%d\n",len);
69     for(i=0;i<len;i++)
70     {
71         printf("%05d %d ",finalarr[i],Initarr[finalarr[i]].key);//先按格式输出首地址和键值;首地址按顺序存在final数组中,键值直接访问Init即可
72         if(i==len-1)
73             printf("-1\n");
74         else
75             printf("%05d\n",finalarr[i+1]);//显然next结点地址在i+1里
76         
77     }
78     
79     return 0;
80 }

 

264.反转链表

时间限制: 2 秒

内存限制: 256KB

问题描述

输入一个链表,反转链表后,输出链表的所有元素。

 

输入说明

输入第一行为整数n(n>=1),代表测试链表数。

从第二行开始每行表示一个链表,其中第一个数据表示链表中数据个数,其余数据表示要测试的链表中的数据,均为整数。 

输出说明

每一行对应一个链表反转后的元素。

 

输入样例

3

5 1 2 3 4 5

3 2 4 5

1 3

输出样例

5 4 3 2 1

5 4 2

3

两种写法  1 //想要反向输出只能写成双向链表?如果是单链表怎么操作?用数组也就是静态   2 //链表来模拟?  3 //

  4 // Created by Administrator on 2023/10/27/027.
  5 //
  6 
  7 /*试题名称    反转链表
  8 时间限制:    2 秒
  9 内存限制:    256KB
 10 
 11 问题描述
 12 输入一个链表,反转链表后,输出链表的所有元素。
 13 
 14 输入说明
 15 输入第一行为整数n(n>=1),代表测试链表数。
 16 从第二行开始每行表示一个链表,其中第一个数据表示链表中数据个数,其余数据表示要测试的链表中的数据,均为整数。
 17 
 18 输出说明
 19 每一行对应一个链表反转后的元素。
 20 
 21 输入样例
 22 3
 23 5 1 2 3 4 5
 24 3 2 4 5
 25 1 3
 26 
 27 输出样例
 28 5 4 3 2 1
 29 5 4 2
 30 3
 31 
 32 
 33 这个方法选取的是:
 34  直接用头插法建立单链表然后从头指针往后读取即可
 35  直接输出的话有个问题就是他会更新单链表,所以需要一个存储链表头指针的数组-》这个适用于你想要输入完全部再统一输出的情况,事实上直接输入一遍后输出一边oj不会管
 36  第二个问题是在oj里超时了
 37 
 38  提交成功后加了一些printf语句打印方便观看,用于oj可以注释掉
39 */ 40 41 #include <stdio.h> 42 #include <stdlib.h> 43 44 typedef struct node 45 { 46 int data; 47 struct node *next; 48 }Linklist; 49 50 Linklist* headCreate(int len) 51 { 52 Linklist *head,*newData; 53 int my_data,i=0; 54 head=(Linklist*)malloc(sizeof(Linklist)); 55 head->next=NULL; 56 head->data=len; 57 for(i=0;i<len;i++) 58 { 59 newData=(Linklist*) malloc(sizeof(Linklist)); 60 scanf("%d",&my_data); 61 newData->data=my_data; 62 newData->next=head->next; 63 head->next=newData; 64 //要注意到头插法的特点是先进的在队尾,新的元素不断接在头结点的后面称为第一结点 65 } 66 return head; 67 } 68 69 void Visit_Linklist(Linklist *head) 70 { 71 Linklist *find; 72 find=head->next; 73 while(find!=NULL) 74 { 75 printf("%d\t",find->data); 76 find=find->next; 77 } 78 printf("\n"); 79 } 80 81 int main() 82 { 83 int sum,cnt,singleLen; 84 printf("请输入总的链表数:\n"); 85 scanf("%d",&sum); 86 87 Linklist ** lists = (Linklist **)malloc(sum * sizeof(Linklist *));//新建一个数组来存取每次的头指针,并用下标给定他唯一的标识符 88 //注意这个写法 89 printf("请输入每个链表的元素数和元素:\n"); 90 for(cnt=0;cnt<sum;cnt++) 91 { 92 scanf("%d",&singleLen); 93 lists[cnt]=headCreate(singleLen); 94 } 95 96 printf("反转后的链表是:\n"); 97 for(cnt=0;cnt<sum;cnt++) 98 { 99 Visit_Linklist(lists[cnt]); 100 } 101 102 //或者写成下面的输出也行: 103 /* 把list那个注释掉 104 * for(cnt=0;cnt<sum;cnt++) 105 { 106 scanf("%d",&singleLen); 107 Linklist *head=headCreate(singleLen); 108 Vist_Linklist(head); 109 } 110 */ 111 112 113 /* 114 1.在函数headCreate()中,使用了一个循环来读取输入数据并创建链表节点。 115 但是在每次循环时都调用getchar()来读取字符直到遇到换行符,这可能会导致程序在等待输入时耗费大量时间。(这个有可能是主要原因) 116 建议改为使用scanf函数读取整数,并在输入结束后清空缓冲区。 117 118 尝试改进后重新试下oj超时的问题 119 120 事实上验证了确实是这个getchar的问题,本来用的课本的例程代码,不过显然没考虑具体题目的时间限制情况 121 */ 122 123 return 0; 124 125 126 }

 

还有一种方法是尾插法然后用指针来转换。懒得把链表基本实现的函数写完了,,,

 

 1 //
 2 // Created by Administrator on 2023/10/27/027.
 3 //这个方法考虑的是尾插创建单链表再头插建新链表输出,实现倒序,可以看出尾插类似队列,头插类似栈
 4 #include <stdio.h>
 5 #include <stdlib.h>
 6 
 7 typedef struct node
 8 {
 9     int data;
10     struct node *next;
11 }Linklist;
12 
13 Linklist* reverseLinklist(Linklist *head)//反转链表,换为头插法
14 {
15     Linklist *new_head,*current;
16     new_head=NULL;
17     current=head;
18     while (current != NULL) {
19         Linklist * nextNode = current->next;//更新,将nextnode指针指向现指针指向位置的下一个结点(存储下一个结点的信息)
20         current->next = new_head;//将现指针的后继指针指向新链表的头指针,如一开始是指向NULL,下一次是指向上一个填入的结点
21         new_head = current;//更新头指针,新链表头指针指向现指针指向的结点,即赋值插入元素,由于上一步已经有current->next=newhead,实际完成了链接!
22         current = nextNode;//移动现指针到指向原链表的下一结点
23     }
24 
25     return new_head; // 返回新的头结点
26 }
27 
28 void Visit_Linklist(Linklist *head)
29 {
30     Linklist *find;
31     find=head;
32     while(find!=NULL)
33     {
34         printf("%d\t",find->data);
35         find=find->next;
36     }
37     printf("\n");
38 }
39 
40 int main()
41 {
42     int n; // 测试链表数
43     scanf("%d", &n);
44     int i,j;
45     for (i = 0; i < n; i++)
46     {
47         int len; // 链表长度
48         scanf("%d", &len);
49         Linklist *head,*tail;
50         head=NULL;
51         tail=NULL;
52         for (j = 0; j < len; j++)
53         {
54             int my_data;//尾插法存数据
55             Linklist *newData;
56             newData=(Linklist*) malloc(sizeof(Linklist));//给存储数据的新临时结点开辟空间
57             scanf("%d",&my_data);
58             newData->data=my_data;
59             if(head==NULL)//没有头结点,空表,头指针指向第一个填入的元素
60                 head=newData;
61             else
62                 tail->next=newData;//非空表,head不指向空,那么就讲tail后继指向新结点实现连接
63             tail=newData;//不管是空表的第一种情况,还是后续的非空表,都要有尾指针指向新临时结点
64         }
65         if(tail!=NULL)
66             tail->next=NULL;//尾插法单链表,最后尾指针后继指向空
67 
68         head=reverseLinklist(head);
69         Visit_Linklist(head);
70 
71         //可以在后面补一个释放内存的把链表内存释放了,养成好习惯
72     }
73 
74 }

 

 

标签:Linklist,结点,顺序,15,head,next,链表
From: https://www.cnblogs.com/WCMS-XDU688/p/17808737.html

相关文章

  • 数据结构之链表
    1.简介链表(LinkedList)是一种基本的数据结构,用于表示一组元素,这些元素按顺序排列,每个元素都与下一个元素连接。与数组不同,链表的元素不是在内存中连续存储的,而是通过指针来连接的。链表由节点(Node)组成,每个节点包含两个主要部分:数据和指向下一个节点(或上一个节点,如果是双向链表)的......
  • Java面试题:链表-合并两个排序的链表
    描述输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。示例输入:{1,3,5},{2,4,6}返回值:{1,2,3,4,5,6}原题地址:https://www.nowcoder.com/practice/d8b6b4358f774294a89de2a6ac4d9337代码实现packagecom.example.demo.linked;......
  • Java面试题:链表-反转链表
    问题描述给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。如当输入链表{1,2,3}时,经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。示例输入:{1,2,3}返回值:{3,2,1}原题地址:https://www.nowcoder.com/practice/7......
  • 寻找两个链表相交节点方法(可以是有环链表)
    问题分析:两个链表相交可以分为两个大类,一是两个无环链表相交,二是两个有环链表相交。 无环相交如图:有环相交有两种情况,一种是先相交后成环,如图:另一种是交点有两个,是成环后的交点(入环节点不同) 方法1.判断链表是否有环,返回第一个入环节点。2.判断是否相交3.......
  • 双向链表结构分析
    双向链表描述双向链表也叫双链表,它的每个数据结点都有两个指针,分别指向前驱结点和后继节点,同时有一个数据域来保存数据,双向链表的图示如下:从图片可以看出,双链表的头结点的前驱结点和尾结点的后继结点为空,这一点要注意,对双链表的操作要检查这两种情况。双向链表结构每个数据结......
  • [20231023]为什么刷新缓存后输出记录顺序发生变化6.txt
    [20231023]为什么刷新缓存后输出记录顺序发生变化6.txt--//前几天做了单表刷新缓存后输出记录顺序发生变化的情况,测试2个表的情况时遇到一个奇怪的现象。--//我前面的测试18c,如果使用10046跟踪看不到我遇到的情况,我想使用strace跟踪,发现该机器配置使用asm,strace跟踪无法看到一--/......
  • 查询算法——顺序查找(优化),二分查找(递归)
    顺序查找顺序查找又称为线性查找,是一种最简单的查找方法。适用于线性表的顺序存储结构和链式存储结构,从第一个元素开始逐个与需要查找的元素x进行比较,当比较到元素值相同时,返回元素m的下标,如果比较到最后都没有找到,则返回-1;时间复杂度为O(n)点击查看代码publicstaticvoidm......
  • 牛客剑指offer刷题链表篇
    @[TOC]从尾到头打印链表题目输入一个链表的头节点,从尾到头反过来打印出每个节点的值。思路利用栈后进先出的性质实现;代码实现privatestaticvoidprintReverseNode(ListNodehead){if(head==null){return;}ListNodepNode=head;......
  • 《安富莱嵌入式周报》第320期:键盘敲击声解码, 军工级boot设计,开源CNC运动控制器,C语言
     视频版:https://www.bilibili.com/video/BV1Cr4y1d7Mp/1、键盘敲击声解码https://arxiv.org/abs/2308.01074键盘敲击声被解码的话,我们使用键盘输入密码将被方便的解码出来。这篇文章介绍了一种使用最先进的深度学习模型,以便使用手机麦克风对笔记本电脑敲击键盘分析。实际测试训练......
  • `async` 函数没有使用 `await` 的执行顺序
    async函数没有使用await的执行顺序什么是async函数?async是JavaScript中的一个关键字,用于定义异步函数。异步函数返回一个Promise对象,但如果没有使用await,它将不会等待异步操作的完成。基本概念在async函数内没有使用await时,执行顺序遵循以下基本原则:立即执行async函......