第十一讲 链表编程题

合集下载

链表的一些常见笔试面试问题总结及代码

链表的一些常见笔试面试问题总结及代码

假设链表节点的数据结构为:struct node{int data;struct node* next;};创建单链表的程序为:struct node* create(unsigned int n){//创建长度为n的单链表assert(n > 0);node* head;head = new node;head->next = NULL;cout << "请输入head节点的值(int型):"; cin >> head->data;if (n == 1){return head;}node* p = head;for (unsigned int i = 1; i < n; i++) {node* tmp = new node;tmp->next = 0;cout << "请输入第" << i+1 << "个节点的值(int):";cin >> tmp->data;p->next = tmp;p = tmp;}return head;}问题1:链表逆置思想为:head指针不断后移,指针反向即可,代码为:void reverse(node*& head){if (head != NULL && head->next != NULL) {node* p = head;node* q = head->next;p->next = NULL;while (q->next != NULL){head = q->next;q->next = p;p = q;q = head;}head->next = p;}return;}问题2:删除不知头结点链表的某个节点如果单向链表不知道头节点,一个指针指向其中的一个节点,问如何删除这个指针指向的节点?思想为:把这个节点的下一个节点的值复制给该节点,然后删除下一个节点即可。

c语言 链表笔试题

c语言 链表笔试题

关于链表常考的笔试面试题1、单链表逆序,在原列表的基础上进行调整struct ListNode* ReverseList(struct ListNode* pHead ){// write code here//判断第一个元素是否为空,如果为空,则返回NULL;并判断第二个元素是否为空,如果为空,则不需要逆序,直接返回if(pHead == NULL || pHead->next == NULL) return pHead;//定义三个节点指针,分别存放前一个操作节点,当前操作节点,下一个操作节点struct ListNode *temp1 = NULL,*temp2 = pHead,*temp3 = pHead->next;//当下一个操作节点存在时,执行循环,将当前节点的next指向前一个节点,并移动三个指针位置while(NULL != temp3){temp2->next = temp1;temp1 = temp2;temp2 = temp3;temp3 = temp2->next;}//当temp3为空时,说明temp2指向最后一个节点,只需将它的next指向前一个节点temp2->next = temp1;return temp2;}2、找出链表的倒数第n个节点int query_reverse(List* list,size_t index){Node* f = list->head;Node* s = list->head;for(int i=0;i<index;i++){f = f->next;if(f == NULL) return false;}while(f){f = f->next;s = s->next;}return s->data;3、判断链表中是否有环bool is_ring(List* list){Node* fast = list->head;//快指针Node* slow = list->head;//慢指针while(fast && fast->next){fast = fast->next->next;//快指针每次走两步slow = slow->next;//慢指针每次走一步if(slow == fast) return true;//如果相同,则该链表有环}return false;}4、找到环形链表的入口int ring_in(List* list){if(is_ring){Node* fast = list->head;Node* slow = list->head;Node* meet = list->head;while(fast && fast->next){fast = fast->next->next;slow = slow->next;meet = meet->next;if(slow == fast){slow = list->head;fast = meet;fast = fast->next;slow = slow->next;if(slow == fast)return fast->data;}}}return -1;}5、合并两个有序链表,合并后依然有序List* merge_list(List* list1,List* list2){Node* m = list1->head->next;Node* n = list2->head->next;Node* new = create_node();if(list1 == NULL) return list2;if(list2 == NULL) return list1;if(list1== NULL && list2== NULL) return NULL;while(list1&&list2){if(m->data < n->data){new->next = m;m = m->next;}else{new->next = n;n = n->next;}new = new->next;}new->next = m?m:n;return new;}6、判断两个链表是否是Y型链表bool is_y(List* l1,List* l2){int cnt1 = 0,cnt2 = 0;Node* m = l1->head->next;Node* n = l2->head->next;while(m){cnt1++;m = m->next;}while(n){cnt2++;n = n->next;}if(cnt1>cnt2){for(int i=0;i<cnt1-cnt2;i++){m = m->next;}}else{for(int i=0;i<cnt2-cnt1;i++){n = n->next;}}while(m == NULL || n = NULL){m = m->next;n = n->next;if(m = n) return true;}return false;}。

链表的刷题套路

链表的刷题套路

链表的刷题套路
链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。

链表在计算机科学中被广泛使用,因此掌握链表的相关算法非常重要。

下面是一些常见的链表题目及其解题思路:
1. 单向链表的长度
题目描述:给定一个单向链表,返回链表的长度。

解题思路:遍历链表,使用一个计数器记录链表的长度。

2. 双向链表的中间节点
题目描述:给定一个双向链表的头节点,返回链表的中间节点。

解题思路:可以使用快慢指针的方法。

两个指针同时从头节点开始遍历,一个指针每次前进一步,另一个指针每次前进两步。

当快指针到达链表末尾时,慢指针正好在中间节点。

3. 反转链表
题目描述:给定一个单向链表的头节点,反转链表并返回反转后的链表。

解题思路:可以使用迭代或递归的方法。

迭代方法需要使用三个指针,分别指向当前节点、前一个节点和后一个节点。

递归方法需要先递归到链表的倒数第二个节点,然后改变指针的指向即可。

4. 合并两个有序链表
题目描述:给定两个升序链表,合并它们并返回一个升序链表。

解题思路:可以使用归并排序的思想。

分别遍历两个链表,将较小的节点添加到结果链表中,同时更新指针的指向。

最后返回结果链表的头节点即可。

5. 删除链表中的重复元素
题目描述:给定一个单向链表,删除所有重复的元素,只留下每个元素出现一次的节点。

解题思路:可以使用哈希表或双指针的方法。

哈希表方法需要使用一个哈希表来记录每个元素是否出现过。

双指针方法需要同时遍历链表,当发现有重复元素时删除该元素并更新指针的指向。

链表练习题及答案

链表练习题及答案

1、已知L是带表头的单链表,其P结点既不是首元结点,也不是尾元结点,a.删除p结点的直接后继的语句是11,3,14b.删除p结点的直接前驱的语句是10,12,8,11,3,14c.删除p结点的语句序列是10,7,3,14d.删除首元结点的语句序列是12,10,13,14e.删除尾元结点的语句序列是9,11,3,14(1)p=p->next;(2) p->next=p;(3)p->next=p->next->next;(4)p=p->next->next;(5)while(p)p=p->next;(6)whlie(Q->next){p=Q;Q=Q->next;}(7)while(p->next!=Q)p=p->next;(8)while(p->next->next!=Q)p=p->next;(9)while(p->next->next)p=p->next;(10)Q=p;(11)Q=p->next;(12)p=L;(13)L=L->next;(14)free(Q);2、已知L是带表头的单链表,其P结点既不是首元结点,也不是尾元结点,a.在p结点后插入s结点的语句序列是4,1b.在p结点前插入s结点的语句序列是7,11,8,4,1c.在表首插入s结点的语句序列是5,12d.在表尾插入s结点的语句序列是7,9,4,1或11,9,1,61.p-> next =s;2.p-> next=p-> next-> next;3.p->next=s->next;4.s->next=p-> next;5.s-> next=L;6.s->next=NULL;7.q=p ;8.while(p->next!=q) p=p->next;9.while(p->next!=NULL) p=p->next;10.p =q;11.p=L;12.L=s;13.L=P;3、已知P结点是某双向链表的中间结点,从下列提供的答案中选择合适的语句序列a.在P结点后插入S结点的语句序列是12,7,3,6b.在P结点前插入S结点的语句序列是13,8,5,4c.删除p结点的直接后继结点的语句序列是15,1,11,18d.删除p结点的直接前驱结点的语句序列是16,2,10,18e.删除p结点的语句序列是9,14,171.P->next=P->next->next;2.P->priou=P->priou->priou;3.P->next=S;4.P->priou=S;5.S->next=P;6.S->priou=P;7.S->next=P->next;8.S->priou=P->priou;9.P->priou->next=P->next;10.P->priou->next=P;11.P->next->priou=P;12.P->next->priou=S;13.P->priou->next=S;14.P->next->priou=P->priou;15.Q=p->next;16.Q=P->priou;17.free(P);18.free(Q);。

链表排序(冒泡、选择、插入、快排、归并、希尔、堆排序)

链表排序(冒泡、选择、插入、快排、归并、希尔、堆排序)

链表排序(冒泡、选择、插⼊、快排、归并、希尔、堆排序)这篇⽂章分析⼀下链表的各种排序⽅法。

以下排序算法的正确性都可以在LeetCode的这⼀题检测。

本⽂⽤到的链表结构如下(排序算法都是传⼊链表头指针作为参数,返回排序后的头指针)struct ListNode {int val;ListNode *next;ListNode(int x) : val(x), next(NULL) {}};插⼊排序(算法中是直接交换节点,时间复杂度O(n^2),空间复杂度O(1))class Solution {public:ListNode *insertionSortList(ListNode *head) {// IMPORTANT: Please reset any member data you declared, as// the same Solution instance will be reused for each test case.if(head == NULL || head->next == NULL)return head;ListNode *p = head->next, *pstart = new ListNode(0), *pend = head;pstart->next = head; //为了操作⽅便,添加⼀个头结点while(p != NULL){ListNode *tmp = pstart->next, *pre = pstart;while(tmp != p && p->val >= tmp->val) //找到插⼊位置{tmp = tmp->next; pre = pre->next;}if(tmp == p)pend = p;else{pend->next = p->next;p->next = tmp;pre->next = p;}p = pend->next;}head = pstart->next;delete pstart;return head;}};选择排序(算法中只是交换节点的val值,时间复杂度O(n^2),空间复杂度O(1))class Solution {public:ListNode *selectSortList(ListNode *head) {// IMPORTANT: Please reset any member data you declared, as// the same Solution instance will be reused for each test case.//选择排序if(head == NULL || head->next == NULL)return head;ListNode *pstart = new ListNode(0);pstart->next = head; //为了操作⽅便,添加⼀个头结点ListNode*sortedTail = pstart;//指向已排好序的部分的尾部while(sortedTail->next != NULL){ListNode*minNode = sortedTail->next, *p = sortedTail->next->next;//寻找未排序部分的最⼩节点while(p != NULL){if(p->val < minNode->val)minNode = p;p = p->next;}swap(minNode->val, sortedTail->next->val);sortedTail = sortedTail->next;}head = pstart->next;delete pstart;return head;}};快速排序1(算法只交换节点的val值,平均时间复杂度O(nlogn),不考虑递归栈空间的话空间复杂度是O(1))这⾥的partition我们参考(选取第⼀个元素作为枢纽元的版本,因为链表选择最后⼀元素需要遍历⼀遍),具体可以参考这⾥我们还需要注意的⼀点是数组的partition两个参数分别代表数组的起始位置,两边都是闭区间,这样在排序的主函数中:void quicksort(vector<int>&arr, int low, int high){if(low < high){int middle = mypartition(arr, low, high);quicksort(arr, low, middle-1);quicksort(arr, middle+1, high);}}对左边⼦数组排序时,⼦数组右边界是middle-1,如果链表也按这种两边都是闭区间的话,找到分割后枢纽元middle,找到middle-1还得再次遍历数组,因此链表的partition采⽤前闭后开的区间(这样排序主函数也需要前闭后开区间),这样就可以避免上述问题class Solution {public:ListNode *quickSortList(ListNode *head) {// IMPORTANT: Please reset any member data you declared, as// the same Solution instance will be reused for each test case.//链表快速排序if(head == NULL || head->next == NULL)return head;qsortList(head, NULL);return head;}void qsortList(ListNode*head, ListNode*tail){//链表范围是[low, high)if(head != tail && head->next != tail){ListNode* mid = partitionList(head, tail);qsortList(head, mid);qsortList(mid->next, tail);}}ListNode* partitionList(ListNode*low, ListNode*high){//链表范围是[low, high)int key = low->val;ListNode* loc = low;for(ListNode*i = low->next; i != high; i = i->next)if(i->val < key){loc = loc->next;swap(i->val, loc->val);}swap(loc->val, low->val);return loc;}};快速排序2(算法交换链表节点,平均时间复杂度O(nlogn),不考虑递归栈空间的话空间复杂度是O(1))这⾥的partition,我们选取第⼀个节点作为枢纽元,然后把⼩于枢纽的节点放到⼀个链中,把不⼩于枢纽的及节点放到另⼀个链中,最后把两条链以及枢纽连接成⼀条链。

c语言练习题6(数组与链表,有答案)

c语言练习题6(数组与链表,有答案)

1、(1)数据结构中,与所使用的计算机无关的是数据的_C_______。

A)存储结构B)物理结构C)逻辑结构D)物理和存储结构评析:数据结构概念一般包括3个方面的内容,数据的逻辑结构、存储结构及数据上的运算集合。

数据的逻辑结构只抽象的反映数据元素之间的逻辑关系,而不管它在计算机中的存储表示形式。

2、栈底至栈顶依次存放元素A、B、C、D,在第五个元素E入栈前,栈中元素可以出栈,则出栈序列可能是____D____。

A)ABCED B)DBCEA C)CDABE D)DCBEA评析:栈操作原则上“后进先出”,栈底至栈顶依次存放元素A、B、c、D,则表明这4个元素中D是最后进栈,B、c处于中间,A最早进栈。

所以出栈时一定是先出D,再出c,最后出A。

3、线性表的顺序存储结构和线性表的链式存储结构分别是____B____。

A)顺序存取的存储结构、随机存取的存储结构B)随机存取的存储结构、顺序存取的存储结构C)随机存取的存储结构、随机存取的存储结构D)任意存取的存储结构、任意存取的存储结构评析:顺序存储结构中,数据元素存放在一组地址连续的存储单元中,每个数据元素地址可通过公式LOC(ai)。

LOC(a1)+(i-1)L计算得到,从而实现了随机存取。

对于链式存储结构,要对某结点进行存取,都得从链的头指针指向的结点开始,这是一种顺序存取的存储结构。

4、在单链表中,增加头结点的目的是____A__。

A)方便运算的实现B)使单链表至少有一个结点C)标识表结点中首结点的位置D)说明单链表是线性表的链式存储实现评析:头结点不仅标识了表中首结点的位置,而且根据单链表(包含头结点)的结构,只要掌握了表头,就能够访问整个链表,因此增加头结点目的是为了便于运算的实现。

5、数据处理的最小单位是___C_____。

A)数据B)数据元素C)数据项D)数据结构评析:数据处理的最小单位是数据项;由若干数据项组成数据元素;而数据是指能够被计算机识别、存储和加工处理的信息载体;数据结构是指数据之间的相互关系和数据运算。

链表 应用题

链表应用题
链表是一种常用的数据结构,可以用来解决很多实际问题。

下面是一些链表的应用题:
1. 约瑟夫环问题:约瑟夫环问题是一个经典的链表问题,通常使用单向循环链表来解决。

在这个问题中,n个人围坐在一张圆桌周围,从编号为k的人开始报数,数到m的那个人出列,然后下一个人继续从1开始报数,直到所有人出列。

解决问题的关键是建立一个单向循环链表,然后从链表第一个结点起循环计数寻找第m个结点,并输出该结点的id值。

接着根据m值不断从链表中删除结点,直到链表为空。

2. 反转链表:反转链表也是一个经典的链表问题。

给定一个链表的头节点,将链表中的节点反转。

可以使用迭代或递归的方法来解决这个问题。

具体实现方法是将链表的头节点存储在一个指针变量中,然后从头节点开始遍历链表,每次将当前节点的next指针指向前一个节点,直到遍历完整个链表。

最后返回头节点即可。

3. 合并两个有序链表:给定两个升序链表,合并它们为一个新的升序链表并返回。

新链表是通过拼接给定的两个链表的所有节点组成的。

可以使用双指针法来解决这个问题。

具体实现方法是分别从头节点开始遍历两个链表,每次比较两个节点的值,将较小的节点加入到新链表中,直到遍历完其中一个
链表。

然后继续遍历另一个链表,将剩余的节点加入到新链表中。

最后返回新链表的头节点即可。

以上是几个常见的链表应用题,使用不同的方法可以解决不同的问题。

解决这些问题的关键是理解链表的基本操作和性质,并能够根据具体问题选择合适的数据结构和算法。

PTA——链表——相关习题(程设二)

PTA——链表——相关习题(程设⼆)今天⼜是整理代码的⼀天呐( 。

_ 。

) ✎ _代码链接1 #include <stdio.h>2 #include <stdlib.h>34 typedef struct Node5{6int data;7struct Node *next;8}node;910 node *creat(int n) //尾插法建⽴链表11{1213 node *head,*p,*tail; //创建新节点并置空14 head=(node*)malloc(sizeof(node));1516 head->next=NULL;17 tail=head; //此时只有链表中只有⼀个节点1819for(int i=0;i<n;i++)20 {21 p=(node*)malloc(sizeof(node)); //开辟新节点22 scanf("%d",&p->data);2324 p->next=NULL;25 tail->next=p;26 tail=p; //将tail更新为p,相当于尾部多了⼀个节点,此时tail仍然指的是尾部27 }28return head; //返回头节点2930}3132void pri(node *p)33{34while(p)//遍历链表35 {36if(p->next==NULL)37 printf("%d",p->data);38else printf("%d ",p->data);39 p=p->next;40 }代码链接41 }4243 void solve()44 {4546 int n;47 scanf("%d", &n);4849 node *head;50 head=creat(n); //建⽴链表5152 pri(head->next); //遍历输出链表的值5354 }5556 int main()57 {5859 int T=1;60 //scanf("%d",&T);61 while (T--)62 solve();6364 return 0;65 }7-1数据结构实验之链表⼀:顺序建⽴链表1 #include <stdio.h>2 #include <stdlib.h>34 typedef struct Node5 {6 int data;7 struct Node *next;8 }node;910 node *creat(int n) //头插法建⽴链表11 {1213 node *head,*p; //创建新节点并置空1415 head=(node*)malloc (sizeof (node));16 head->next=NULL;1718for(int i=0;i<n;i++)19 {20 p=(node*)malloc(sizeof(node));21 scanf("%d",&p->data);2223 p->next=head->next; //p现在指向head的下⼀位24 head->next=p; //再让head指向p相当于p完成了插⼊操作,插到了head和head->next的中间部分25 }2627return head; //返回头节点2829}3031void pri(node *p)32{33while(p)//遍历链表34 {35if(p->next==NULL)36 printf("%d",p->data);37else printf("%d ",p->data);38 p=p->next;39 }40}4142void solve()43{4445int n;46 scanf("%d", &n);4748 node *head;49 head=creat(n); //建⽴链表5051 pri(head->next); //遍历输出链表的值5253}5455int main()56{5758int T=1;59//scanf("%d",&T);60while(T--)61 solve();6263return0;64 }7-2 数据结构实验之链表⼆:逆序建⽴链表代码链接1 #include <stdio.h>2 #include <stdlib.h>34 typedef struct Node5{6int data;7struct Node *next;8}node;910 node *creat() //头插法建⽴链表11{1213int k;14 node *head,*p,*tail;1516 head=(node*)malloc(sizeof(node));17 head-> next = NULL;18 tail=head;1920while(~scanf("%d",&k) && k!=-1)21 {22 p=(node*)malloc(sizeof(node));23 p->data=k;24 p->next=NULL;25 tail->next=p;26 tail=p;27 }2829return head;3031}3233void reserve(node *head)//倒置34{35 node *p,*s; //定义两个指针3637 p=head->next;38 head->next=NULL;3940while(p)41 {42 s=p;43 p=p->next; //p和s是两个相邻的指针(p在s后⾯⼀位)44 s->next=head->next; //s->next第⼀次置空,第⼆次指向第⼀个数,遍历(参考下⼀⾏)45 head->next=s; //head指向的位置越来越靠后46 }47}4849void pri(node *p)50{51while(p)//遍历链表52 {53if(p->next==NULL)54 printf("%d\n",p->data);55else printf("%d ",p->data);56 p=p->next;57 }58}5960void solve()61{62 node *head;6364 head=creat(); //建⽴链表65代码链接66 reserve(head);6768 pri(head->next);6970 }7172 int main()73 {7475 int T=1;76 //scanf("%d",&T);77 while (T--)78 solve();7980 return 0;81 }7-3数据结构实验之链表三:链表的逆置1 #include <stdio.h>2 #include <stdlib.h>34 typedef struct Node5 {6 int data;7 struct Node *next;8 }node;910 node *creat(int n) //尾插法建⽴链表11 {1213 node *head,*p,*tail; //创建新节点并置空14 head=(node*)malloc (sizeof (node));1516 head->next=NULL;17 tail=head; //此时只有链表中只有⼀个节点1819 for (int i=0;i<n;i++)20 {21 p=(node*)malloc (sizeof (node)); //开辟新节点22 scanf("%d",&p->data);2324 p->next=NULL;25 tail->next=p;26 tail=p; //将tail更新为p,相当于尾部多了⼀个节点,此时tail仍然指的是尾部27 }28return head; //返回头节点2930}3132 node *Merge(node *head1,node *head2) //归并算法典中典了属于是33{3435 node *p1,*p2,*tail;3637 p1=head1->next;38 p2=head2->next;39 tail=head1;4041while(p1 && p2)42 {43if(p1->data<=p2->data) //⽐较两个data的值看指针指向哪⼀个44 {45 tail->next=p1;46 tail=p1;47 p1=p1->next;48 }49else50 {51 tail->next=p2;52 tail=p2;53 p2=p2->next;54 }55 }56if(p1) //跳出循环是因为有⼀⽅数据输⼊完毕,判断哪个链表还有剩余,接上尾巴即可 57 tail->next=p1;58else59 tail->next=p2;6061return head1;6263}6465void pri(node *p)66{67while(p)//遍历链表68 {69if(p->next==NULL)70 printf("%d",p->data);71else printf("%d ",p->data);72 p=p->next;73 }74}7576void solve()77{7879int n,m;80 scanf("%d %d", &n,&m);8182 node *head1,*head2;8384 head1=creat(n);85 head2=creat(m); //建⽴链表8687 head1=Merge(head1,head2);8889 pri(head1->next); //遍历输出链表的值9091}9293int main()94{代码链接96 int T=1;97 //scanf("%d",&T);98 while (T--)99 solve();100101 return 0;102 }7-4数据结构实验之链表四:有序链表的归并1 #include <stdio.h>2 #include <stdlib.h>34 typedef struct Node5 {6 int data;7 struct Node *next;8 }node;910 int n;11 int len1,len2;1213 node *creat(int n) //尾插法建⽴链表14 {1516 node *head,*p; //创建新节点并置空1718 head=(node*)malloc (sizeof (node));19 head->next=NULL;2021 for (int i=0;i<n;i++)22 {23 p=(node*)malloc (sizeof (node));24 scanf("%d",&p->data);2526 p->next=head->next; //p 现在指向head 的下⼀位27 head->next=p; //再让head 指向p 相当于p 完成了插⼊操作,插到了head 和head->next 的中间部分 28 }2930 return head; //返回头节点313334 node *Divide(node *head1)35{36 node *head2,*p,*s;37 head2=(node*)malloc(sizeof(node)); 3839 head2->next=NULL;40 p=head1->next;41 s=p->next;42 head1->next=NULL;4344while(p)45 {46if(p->data%2==0)47 {48 len1++;49 p->next=head1->next;50 head1->next=p;51 }52else53 {54 len2++;55 p->next=head2->next;56 head2->next=p;57 }58 p=s;59if(s)60 s=s->next;61 }62return head2;63}6465void pri(node *p)66{67while(p)//遍历链表68 {69if(p->next==NULL)70 printf("%d\n",p->data);71else printf("%d ",p->data);72 p=p->next;73 }74}7576void solve()77{7879 scanf("%d",&n);8081 node *head1,*head2;8283 head1=creat(n);84 head2=Divide(head1);8586 printf("%d %d\n",len1,len2);8788 pri(head1->next);89 pri(head2->next);9091}9293int main()94{9596int T=1;97//scanf("%d",&T);98while(T--)99 solve();100101return0;102 }数据结构实验之链表五:单链表的拆分7-5相关代码1 #include <stdio.h>2 #include <stdlib.h>34 typedef struct Node5{6int data;7struct Node *next;8}node;9int n;10 node *creat(int n) //尾插法建⽴链表11{1213 node *head,*p; //创建新节点并置空1415 head=(node*)malloc(sizeof(node));16 head->next=NULL;1718for(int i=0;i<n;i++)19 {20 p=(node*)malloc(sizeof(node));21 scanf("%d",&p->data);2223 p->next=head->next; //p现在指向head的下⼀位24 head->next=p; //再让head指向p相当于p完成了插⼊操作,插到了head和head->next的中间部分25 }2627return head; //返回头节点2829}3031void pri(node *p)32{33while(p)//遍历链表34 {35if(p->next==NULL)36 printf("%d\n",p->data);37else printf("%d ",p->data);38 p=p->next;39 }40}4142void solve()43{4445 scanf("%d", &n);4647 node *head,*p;48 head=creat(n); //建⽴链表4950 printf("%d\n",n);51 pri(head->next); //遍历输出链表的值5253 node *q,*k;54 p=head->next;55 q=head;56while(p) //可以看作暴⼒对⽐57 {58int flag=1;59 k=head->next;60while(k!=p)61 {62if(k->data==p->data)63 {64 flag=0;65 n--;66 q->next=p->next;67 p=p->next;68break;69 }70 k=k->next;71 }72if(flag)73 {74 p=p->next;75 q=q->next;76 }77 }78 printf("%d\n",n);79 pri(head->next);80}8182int main()83{8485int T=1;86//scanf("%d",&T);87while(T--)88 solve();8990return0;91 }7-6 数据结构实验之链表七:单链表中重复元素的删除代码链接1 #include <stdio.h>2 #include <stdlib.h>34 typedef struct Node5{6int data;7struct Node *next;8}node;910void Insert(node *head,int m,int k)11{12 node *q=(node*)malloc(sizeof(node)); //q相当于应该插⼊的节点13 node *p=head;14 q->data=k;15for(int i=0;i<m && p->next!=NULL;i++)16 p=p->next; //找到q插⼊的位置17 q->next=p->next; //⽤头节点插⼊的⽅法插⼊q节点18 p->next=q;19}2021void pri(node *p)22{23while(p)//遍历链表24 {25if(p->next==NULL)26 printf("%d",p->data);27else printf("%d ",p->data);28 p=p->next;29 }30}3132void solve()33{3435int n;36while(~scanf("%d",&n))37 {38 node *head,*p;39 head=(node*)malloc(sizeof(node));代码链接40 head->next=NULL;41 for (int i=0;i<n;i++)42 {43 int m,k;44 scanf("%d%d",&m,&k);4546 Insert(head,m,k);47 }48 pri(head->next);49 puts("");50 }5152 }5354 int main()55 {5657 int T=1;58 //scanf("%d",&T);59 while (T--)60 solve();6162 return 0;63 }7-7 师--链表的结点插⼊1 #include <stdio.h>2 #include <stdlib.h>3 #include <malloc .h>45 typedef struct Node6 {7 int data;8 struct Node *next;9 }node;1011 node *creat(int n)12{13 node *head,*p,*tail;14 p=(node*)malloc(sizeof(node));1516 p->data=1;17 p->next=NULL;18 head=p;19 tail=p;2021for(int i=2; i<=n; i++) //现在head=tail=p=1,从2开始正向建⽴链表(尾插法)22 {23 p=(node*)malloc(sizeof(node));2425 p->data=i;26 p->next=NULL;27 tail->next=p;28 tail=p;29 }30 tail->next=head; //⾸尾相连3132return head;33}3435void solve()36{3738int n,m;39int cnt=0;4041 scanf("%d %d",&n,&m);42 node *head,*p,*s;4344 head=creat(n);45 s=head;4647while(s->next!=head) //s表⽰为队尾的元素48 s=s->next;4950while(s->next!=s) //当链表中直剩下⼀个元素时跳出51 {52 p=s->next; //第⼀轮第⼀个数是链表中第⼀个元素,所以起始应该是队尾的元素(p在s前⾯)53 cnt++;//每次喊数字54if(cnt==m)55 {56 s->next=p->next;57free(p); //释放节点p,并将cnt归零重新计数58 cnt=0;59 }60else61 s=p;62 }63 printf("%d",s->data);64656667}6869int main()70{7172int T=1;73//scanf("%d",&T);74while(T--)75 solve();7677return0;78 }7-8 约瑟夫问题代码链接1 #include <stdio.h>2 #include <stdlib.h>34 typedef struct Node5{6int data;7struct Node *next;8struct Node *front;9}node;1011 node *creat(int n) //尾插法建⽴链表12{1314 node *head,*p,*tail; //创建新节点并置空15 head=(node*)malloc(sizeof(node));1617 head->next=NULL;18 head->front=NULL;19 tail=head; //此时只有链表中只有⼀个节点2021for(int i=0;i<n;i++)22 {23 p=(node*)malloc(sizeof(node)); //开辟新节点24 scanf("%d",&p->data);2526 p->next=NULL;27 tail->next=p;28 p->front=tail; //多了⼀个前节点29 tail=p; //将tail更新为p,相当于尾部多了⼀个节点,此时tail仍然指的是尾部30 }31return head; //返回头节点3233}3435void solve()36{3738int n,m;39 scanf("%d %d", &n, &m);4041 node *head;42 head=creat(n); //建⽴链表4344while(m--)代码链接46 int k;47 scanf("%d",&k);4849 node *p=head->next;50 while (p->data!=k)51 p=p->next;52 if (p->front==head)53 printf("%d\n",p->next->data);54 else if (p->next==NULL)55 printf("%d\n",p->front->data);56 else57 printf("%d %d\n",p->front->data,p->next->data);58 }5960 }6162 int main()63 {6465 int T=1;66 //scanf("%d",&T);67 while (T--)68 solve();6970 return 0;71 }7-9数据结构实验之链表九:双向链表1 #include <stdio.h>2 #include <stdlib.h>3 #include <malloc .h>45 typedef struct Node6 {7 int data;8 struct Node *next;9 }node;1011 node *creat(int n)13 node *head,*p,*tail;14 p=(node*)malloc(sizeof(node));1516 p->data=1;17 p->next=NULL;18 head=tail=p;1920for(int i=2; i<=n; i++) //现在head=tail=p=1,从2开始正向建⽴链表(尾插法)21 {22 p=(node*)malloc(sizeof(node));2324 p->data=i;25 p->next=NULL;26 tail->next=p;27 tail=p;28 }29 tail->next=head; //⾸尾相连3031return head;32}3334void solve()35{3637int n;38while(~scanf("%d",&n) && n)39 {40 node *head,*p,*s;41int cnt=0,ans=0;4243 head=creat(n);44 s=head;4546while(s->next!=head)47 s=s->next;4849while(s->next!=s)50 {51 p=s->next;52 cnt++;53if(cnt==5)54 {55 ans++;56if(p->data==1)57break;58 s->next=p->next;59free(p);60 cnt=0;61 }62else63 s=p;64 }65if(s->data==1) //最后⼀次循环提前结束,如果最后剩下⼀号的话需要单独判断66 printf("%d\n",ans+1);67else68 printf("%d\n",ans);69 }70717273}7475int main()76{7778int T=1;79//scanf("%d",&T);80while(T--)81 solve();8283return0;84 }7-10 不敢死队问题⼩结链表的代码较长若不充分李姐(理解)的情况下暴⼒背诵⼀般不会有什么好结果QAQ 重点是理解,懂得建表过程。

单链表算法题

单链表算法题以下是单链表算法题:1. 判断单链表是否有环题目描述:给定一个链表的头节点 head,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。

示例:输入:head = [1,2,3,4], pos = -1输出:false解释:链表中没有环。

解题思路:使用快慢指针法,快指针每次移动两个节点,慢指针每次移动一个节点。

如果存在环,快指针最终会追上慢指针并相遇;如果不存在环,快指针会先到达链表尾部。

2. 单链表插入元素题目描述:给定一个链表的头节点 head 和要插入的位置 pos,以及要插入的元素 value。

在链表中插入新元素后,返回插入后的链表。

示例:输入:head = [1,2,3], pos = 2, value = 4输出:[1,2,4,3]解释:在位置 2 处插入元素 4,得到新的链表 [1,2,4,3]。

解题思路:在链表中插入元素需要先找到要插入的位置的前驱节点,然后将新节点插入到前驱节点和后继节点之间。

如果插入位置为链表第一个位置,则需要创建新节点并将其指向头节点;如果插入位置超过了链表的长度,则无法插入元素。

3. 单链表删除元素题目描述:给定一个链表的头节点 head 和要删除的位置 pos,删除链表中第 pos 个节点(从 1 开始计数),并返回删除后的链表。

示例:输入:head = [1,2,3,4], pos = 2输出:[1,3,4]解释:删除位置 2 上的节点 2,得到新的链表 [1,3,4]。

解题思路:在链表中删除元素需要先找到要删除位置的前驱节点,然后将前驱节点的 next 指针指向要删除节点的后继节点,最后释放要删除节点的内存空间。

如果删除位置为链表第一个位置,则需要修改头节点;如果删除位置超过了链表的长度,则无法删除元素。

链表相关的一些题目

链表相关的⼀些题⽬将单向链表按某值划分成左边⼩、中间相等、右边⼤的形式:【题⽬】给定⼀个单向链表的头节点head,节点的值类型是整型,再给定⼀个整数pivot。

实现⼀个调整链表的函数,将链表调整为左部分都是值⼩于pivot的节点,中间部分都是值等于pivot的节点,右部分都是值⼤于pivot的节点。

除这个要求外,对调整后的节点顺序没有更多的要求。

例如:链表9->0->4->5->1,pivot=3。

调整后链表可以是1->0->4->9->5,也可以是0->1->9->5->4。

总之,满⾜左部分都是⼩于3的节点,中间部分都是等于3的节点(本例中这个部分为空),右部分都是⼤于3的节点即可。

对某部分内部的节点顺序不做要求。

【思路】遍历链表,将链表按pivot值的⼤⼩划分成三个链表,分别为small表、equal表、big表,存储⼩于pivot的元素,等于pivot的元素,⼤于pivot 的元素。

划分完后将三个链表连接起来,返回头指针即可。

【Code】public static class Node{public int value;public Node next;public Node(int value){this.value = value;}}public static Node SmallEqualBig(Node head,int pivot){Node sH = null;Node sT = null;Node eH = null;Node eT = null;Node bH = null;Node bT = null;Node next = null;//将原链表按pivot的值进⾏划分,成三个链表while(head!=null){next = head.next;head.next = null;if(head.value<pivot){if(sH==null){sH = head;sT = head;}else {sT.next = head;//向当前表尾的后继插⼊新节点sT = head;//指针后移到新插⼊的节点}}else if(head.value==pivot){if(eH==null){eH = head;eT = head;}else {eT.next = head;eT = head;}}else {if(bH==null){bT = head;}else {bT.next = head;bT = head;}}head =next;}//将三个链表从⼩中⼤进⾏连接//small连接equal表if(sT!=null){sT.next = eH;eT = eT == null? sT:eT;}//equal表连接big表if(eT!=null){eT.next = bH;}//返回头指针return sH!=null?sH:eH!=null?eH:bH;}复制含有随机指针节点的链表【题⽬】⼀种特殊的链表节点类描述如下:public class Node { public int value; public Node next; public Node rand; public Node(int data) { this.value = data; }}Node类中的value是节点值,next指针和正常单链表中next指针的意义⼀样,都指向下⼀个节点,rand指针是Node类中新增的指针,这个指针可能指向链表中的任意⼀个节点,也可能指向null。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档