数据结构------单链表相关的面试题

【数据结构】面试题整理 共36题 链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据和一个指向下一个节点的指针。与数组不同,链表中的元素在内存中不必是连续存储的,这使得链表在插入和删除操作时非常高效。单向链表(Singly Linked List):每个节点只包含一个指向下一个节点的指针。双向链表(Doubly Linked List):每个节点包含两个指针,一个指向下一个节点,一个指向前一个节点。循环链表(Circular Linked List):链表的最后一个节点指向第一个节点,形成一个环。 阅读详情

1、从尾到头来打印单链表
在以前我们学习C语言的时候,我们都比较熟悉的就是逆序字符、汉诺塔、还有就是实现斐波那契数列的时候我们当时所用的方法就是递归,在这类问题的实现过,我们就对递归这个算法换是比较熟悉的,今天我们就来用递归的思想来实现从尾到头来打印链表。
那么我们刚开始拿到这个题的时候有点困惑,一时半会没想到解决的办法,最后才想到了递归这个方法。我最后得出逆序打印链表主要有三种做法:
1、用递归的方法进行实现,这个方法虽然比较好用,但是不容易想到,代码相对于来说是比较简单的。
2、定义一个新的链表,然后在将第一个元素放入这个新的链表中,然后调用头插的方法,最后能够将链表实现逆序。
3、第三种方法是实现的是定义三指针的方法:
这里写图片描述
每次都采用这种调用头插的方法:依次往后进行每次调用头插之后让三个指针都往后进行遍历,然后在调用头插这样依次进行循环,直到所有的元素都进行逆序完毕。

void LinkListReversePrint(LinkNode* head)    // 逆序打印单链表
{
    if (head == NULL){
        return NULL;
    }
    LinkListReversePrint(head->next);//使用递归的思想来实现
    printf("[%c]|[%p]", head->data, head);
}

2、前面我们已经实现了在pos之前插入一个元素
现在我们就来继续实现下在pos之前去插入元素,条件是在不允许遍历链表的前提下,我们先来说说实现的思想就是我们之前也实现过在pos之后去插入一个元素,我们就将未知的问题就转化为已知的问题,先来在pos之后去插入一个元素,然后将其新插入的元素和pos的值最后激进型交换我们就能实现在pos前去插入一个元素。
我们现在就来用相关的图来演示下我们的思路:
这里写图片描述
具体的代码实现就如下所示:

    void LinkListInsert2(PLinkNode* phead, LinkNode* pos, LinkNodeType value)
    //在这里运用的主要的做法就是先调用后插,然后最后再交换两个位置的值
255 {
256        if(phead == NULL || pos==NULL)
257         {
258             return;
259         }
260         LinkListInsertAfter(phead,pos, value);
261         LinkNodeType ret = pos->data;
262         pos->data = pos->next->data;
263         pos->next->data = ret;
264         return;
265 }

3、单链表实现约瑟夫环
我们先来了解下一个比较有意思的故事:约瑟夫是犹太军队的一个将军,在反抗罗马的起义中,他所率领的军队被击溃,只剩下残余的部队40余人,他们都是宁死不屈的人,所以不愿投降做叛徒。一群人表决说要死,所以用一种策略来先后杀死所有人。
于是约瑟夫建议:每次由其他两人一起杀死一个人,而被杀的人的先后顺序是由抽签决定的,约瑟夫有预谋地抽到了最后一签,在杀了除了他和剩余那个人之外的最后一人,他劝服了另外一个没死的人投降了罗马。
我们这个规则是这么定的:

  • 在一间房间总共有n个人(下标0~n-1),只能有最后一个人活命。
  • 按照如下规则去杀人:
  • 所有人围成一圈
  • 顺时针报数,每次报到q的人将被杀掉 被杀掉的人将从房间内被移走 然后从被杀掉的下一个人重新报数,继续报q,再清除,直到剩余一人

  • 在一间房间总共有n个人(下标0~n-1),只能有最后一个人活命。
    在单链表实现约瑟夫环的过程就如下所示:

266 LinkNode* JosephCycle(LinkNode* head, size_t m)
267     //约瑟夫环
268     //主要实现的是三个步骤:构环,报数、删除
269 {
270           if(head==NULL){
271           return;
272  }
273           size_t count=0;
274           LinkNode* cur=head;
275           LinkNode* tmp= NULL;
276           while(cur->next!=cur){
277         count++;
278         cur=tmp;
279         cur=cur->next;
280         if(count==m)
281         {
282             printf("[%c]\n",tmp->data);
283             LinkListErase2(&tmp,tmp);
284             count=0;
285         }
286           }
287         return cur;
288 }
289          

4、单链表的逆置/反转
在单链表的逆置反转中主要有两种做法:
方法一:
这里写图片描述
代码的实现如下所示:
//这里主要实现的是通过先修改头指针的指向,进行实现的

void LinkListReverse(LinkNode** head)
293 {
294         if(head==NULL){
295         return;
296         }
297         if((*head)->next==NULL){
298         return;
299         }
300         LinkNode* cur=*head;
301         LinkNode* to_erase=NULL;
302         while(cur->next!=NULL)
303        {                                                                                                                           
304         to_erase=cur->next;
305         cur->next=to_erase->next;
306         LinkListPushFront(head,to_erase->data);
307         Destroynode(to_erase); 
308         }
309 }

方法二:
这种方法主要是定义三个指针的方法,进行逆置的,相对来说有点复杂,我们有时候是很不容易去想到的

        //通过定义三个指针的方法
314 void LinkListReverse2(LinkNode** head){
315         if(head==NULL){
316         return;
317         }
318         if((*head)->next==NULL){
319         return;
320         }
321       LinkNode* pre=*head;
322       LinkNode* cur=pre->next;
323       LinkNode* pro=NULL;//pro刚开始必须初始化为空指针,因为每次执行完,所指的内容试不同的
324       while(pre->next!=NULL){
325         pro=cur->next;
326        pre->next=pro;
327        cur->next=pre;
328        cur->next=*head;
329        *head=cur;
330        cur=pre->next;
331         }
332 }                       

5、单链表的冒泡排序
冒泡排序之前我们已经写过很多的比较类似的这种方法实现的不同的要求。

        void swp(LinkNodeType *p1,LinkNodeType  *p2){//刚开始我在这没有定义成指针类型,最后才明白
        形参是实参的一份临时拷贝,必须用指针进行传里面的内容
335 
336     LinkNodeType ret=*p1;
337     *p1=*p2;
338     *p2=ret;
339 }
340 
341 void LinkListBubbleSort(LinkNode** head)
342  // 单链表的冒泡排序
343 {
344         if(head==NULL){
345             return;
346         }
347 
348          LinkNode* cur=*head;//趟数
349          LinkNode* tmp=*head;//次数
350          LinkNode* tal=NULL;//尾指针
351          for(cur=*head;cur->next!=NULL;cur=cur->next){
352              for(tmp=*head;tmp->next!=NULL;tmp=tmp->next){
353                  if((tmp->data)>(tmp->next->data)){
354                      swp(&(tmp->data),&(tmp->next->data));
355                  }
356              }
357          }
358          tmp=tal;
359 }
360 
361 

6、将两个有序的链表合并成一个链表
首先我们定义两个指针指向各自的链表,在定义new_head指向指针的头部,定义new_tail指向尾部,cur1和cur2进行比较,将小的值放入到新链表中。
这里写图片描述
程序需要考虑如下情况:两个链表(函数参数)都有可能为空,可能连个链表其中一个为空,可能两个链表相等,也可能其中一个链表已经遍历完了,另一个链表还有很多元素,所以需要首先处理特殊情况。
1、非递归实现

LinkNode* LinkListMerge(LinkNode* head1, LinkNode* head2)// 将两个有序链表, 合并成一个有序链表
{
    //首先处理特殊情况  两个链表相等;l1为空链表,l2不为空
    //l1不为空,l2为空链表
     //先遍历一次让new_head指向最小的头指针,然后cur1、cur2进行往下走
           LinkNode* cur1=head1;
           LinkNode* cur2=head2;

      if(head1==head2){
          return head1;
      }
      if((head1!=NULL)&&(head2=NULL)){
          return head1;
      }
      if((head1=NULL)&&(head2!=NULL)){
          return head2;
      }
      LinkNode* new_head=NULL;
      LinkNode* new_tail=NULL;
      if((cur1->data)>(cur2->data)){
          new_head=cur2;
          cur2=cur2->next;
      }
     else
     {
          new_head=cur1;
          cur1=cur1->next;
     }
         new_tail=new_head;
              while((cur1!=NULL)&&(cur2!=NULL)){
          if((cur1->data)<(cur2->data)){
        new_tail->next=cur1;
          new_tail=cur1;//new_tail是往后遍历的指针   
          cur1=cur1->next;
          }
          else{
        new_tail->next=cur2;
          new_tail=cur2;
          cur2=cur2->next;
          }
          }
       if(cur1!=NULL){
           new_tail->next=cur1;
       }
      else
      {
           new_tail->next=cur2;
      }
      return new_head;
}

7、找到链表最中间的节点
该题目可算是比较有新意了,我们今天使用的方法是采用快慢指针的方法,之前我们在学习C语言的时候已经接触到了,今天我们就来看看采用这种方法进行解决问题,我们定义一个快指针,一个慢指针,先让慢指针走一步,快指针走两步,当快指针走到最后一个元素的时候,刚好慢指针就走到了最中间的位置,因此也就实现了我们所期望的结果。

  LinkNode* FindMidNode(LinkNode* head)//找到最中间的节点
415 {
416     if(head==NULL){
417         return  NULL;
418     }
419     LinkNode* fast=head;
420     LinkNode* slow=head;
421     while((fast!=NULL)&&(fast->next)!=NULL){//fast走的快,当fast满足条件时,slow肯定满        足条件
422         slow=slow->next;
423         fast=fast->next->next;
424     }
425     return slow;
426 }

8、找到倒数第k个结点,允许只遍历一次
首先我们的思路也是刚才的采用快慢指针的方法,首先让快指针走k步,然后就让slow、fast同时走,知道fast为空时,slow所指的位置就是倒数第k个结点

 LinkNode* FindLastKNode(LinkNode* head, size_t K)//找到倒数第 K 个节点.
431 {
432     if(head==NULL){
433         return;
434     }
435     LinkNode* fast=head;
436     LinkNode* slow=head;
437     int  k=2;//k必须要初始化确定的数值                                                                                             
438     int  i=0;
439     for(i=0;i<k;i++){//先让快指针走k步
440         if(fast==NULL){
441             break;
442         }
443         fast=fast->next;
444     }
445     while(fast!=NULL){//快指针走k步之后,两个指针同时走
446         slow=slow->next;
447         fast=fast->next;
448     }
449     return slow;
450 }
451 

9、删除倒数k个结点
我们先来判断该节点是不是和链表的长度进行比较,在特殊位置的话就采用特殊位置的删除的方法,当k等于所要删除的链表的长度,我们就调用头删,要是超过链表的长度我们就返回,然后再对这些位置进行删除。

void EraseLastKNode(LinkNode** head, size_t K)//删除倒数第K个节点
454 {
455     if(head==NULL){
456         return;
457     }
458     if(*head==NULL){
459         return;
460     }
461     size_t len=LinkListSize(*head);
462     int k=3;//注意要进行初始化,这样才能找到要删的位置
463     if(k>len){
464         return;
465     }
466     if(k==len){                                                                                                                    
467         LinkListPopBack(head);
468     }
469     int i=0;
470     LinkNode* cur=*head;
471     for(i=0;i<len-(k+1);i++){//先让cur找到k结点前面的结点,然后我们所要删除的结点就是
          cur->next,这样再进行删除。
472         cur=cur->next;
473     }
474     LinkNode* to_kill=cur->next;
475     cur->next=to_kill->next;
476     Destroynode(to_kill);
477 }

10、判定单链表是否带环. 如果带环返回1
在判断链表是否代还我们采用的方法也是前面我们所用到的方法,那就是定义两个指针,快指针和慢指针,我们让快指针走两步,慢指针走一步,只要链表带环,两个指针总会相遇的。

int  HasCycle(LinkNode* head)// 判定单链表是否带环. 如果带环返回1
480 {
481     if(head==NULL){
482         return;
483     }
484     LinkNode* fast=head;
485     LinkNode* slow=head;
486     while((fast!=NULL)&&(fast->next!=NULL)){ 
487          fast=fast->next->next;
488          slow=slow->next;
489            if(fast==slow){
490               return 1;
491                }
492            }
493          return 0;
494 }

11、如果链表带环,求环的长度
我们定义两个指针fast和slow两个指针,只要我们知道fast和slow相遇的地点,然后我们再定义一个指针,绕环一周之后,我们得到的就是环的长度。
方法一:

size_t GetCycleLen(LinkNode* head)//如果链表带环, 求出环的长度
495 {
496         if(head==NULL){
497             return;
498         }
499         LinkNode* fast=head;
500         LinkNode* slow=head;
501    while((fast!=NULL)&&(fast->next!=NULL)){ 
502          fast=fast->next->next;
503          slow=slow->next;
504            if(fast==slow)
505                 break;
506            }
507         int count=1;//因为最后一次siow->next=fast,不会进入
508                //循环中,所以次数少加一次,所以count要从1开始
509            while(slow->next!=fast){
510                 count++;
511                slow=slow->next;
512            }
513            return count;
514 }

方法一的简化:

 size_t GetCycleLen2(LinkNode* head)//如果链表带环, 求出环的长度
518  {
519          if(head==NULL){
520              return;
521        }
522         LinkNode* meet = HasCycle(head);//求出快慢指针的相遇点
523         if (meet == NULL){
524                 //不带环的链表
525                 return 0;
526         }
527         LinkNode* cur = meet;
528         size_t count = 1;
529         while (cur->next != meet){ //循环在meet的前一个位置停止,少加一次,count从1开始数
530                 cur = cur->next;
531                 ++count;
532         }
533         return count;
534 }

12、如果链表带环,我们求环的入口点
我们的基本思路就是让头指针从头出发,相遇点指针从相遇点出发,当两个指针重合,那么这点就是我们所要找的入口点。

7 LinkNode* GetCycleEntry(LinkNode* head)// 如果链表带环, 求出环的入口
538 {
539     if(head==NULL){
540         return;
541     }
542          LinkNode* meet= HasCycle(head); 
543          LinkNode* cur=head;
544          LinkNode* cur2=meet;
545         if(meet==NULL){
546         return ;
547         }
548     while(cur!=cur2){
549         cur=cur->next;
550         cur2=cur2->next;
551     }
552     return cur;
553 }

13、判断两个链表是否相交,(假设链表不带环)
首先我们需要知道的是两个链表相交的情况只有Y字型的,没有X字型的。
这里写图片描述
我们的思路就是首先让第一个链表从第一个链表的头节点开始出发,第二个链表也从它的头结点进行出发,最后判断最后一个结点是否相等,那么这两个链表就有交点。

 LinkNode* HasCross(LinkNode* head1, LinkNode* head2)//判定两个链表是否相交, 并求出交点
556 {
557     if(head1==NULL){
558         return   NULL;
559     }
560     if(head2==NULL){                                                                                                               
561         return NULL;
562     }
563     LinkNode* cur1=head1;
564     LinkNode* cur2=head2;
565     while(cur1->next!=NULL){
566         cur1=cur1->next;
567     }
568     while(cur2->next!=NULL){
569         cur2=cur2->next;
570     }
571     if(cur1==cur2){
572         return cur1;
573     }
574     else
575     {
576         return NULL;

14、判断链表是否相交,假设可能带环
1、如果两链表都不带环(相交)
2、两个链表都带环 a、入口相等,交点在环外 b、入口不相等,交点在环上
3、两个链表一个带环,一个不带环,一定不相交

int HasCrossWithCycle(LinkNode* head1, LinkNode* head2)// 判定两个链表是否相交.//但是链表可能带环 ;它的返回值return 如果相交, 返回1, 否则返回0
{ 
    if((head1==NULL)||(head2==NULL))
   {
       return 0;
    }
    LinkNode* entry1=GetCycleEntry(head1);
    LinkNode* entry2=GetCycleEntry(head2);
    //1、如果两链表都不带环(相交)
    if((entry1==NULL)&&(entry2==NULL)){
    return HasCross(head1,head2)!=NULL?1:0;
    }
    //2、两个链表都带环
    if(entry1!=NULL&&  entry2!=NULL){
    //    a、入口相等,交点在环外
           if(entry1==entry2){   
           return 1;
       }
    //    b、入口不相等,交点在环上,两个入口点是不同的,但是能从其中的一个入口绕环几周,最后能到达另外一个入口点,该情况下两个环入口就是链表的交点。
           if(entry1!=entry2){
            LinkNode* cur1=entry1;
          LinkNode* cur2=entry2;
          while(cur1->next!=entry1){
              cur1=cur1->next;
              if(cur1==cur2){
              return 1;
              }
          }
             return  0;
       }
    }
    // 3、两个链表一个带环,一个不带环,一定不相交
    if((entry1!=NULL&& entry2==NULL)||(entry1==NULL &&entry2!=NULL)){
    return 0;
    }

}

15、求两个链表的交集
求两个有序链表的交集的整体思路就是分别定义两个指针 cur1, cur2,指向两个对应的链表的首元素, 然后将 cur1 和 cur2 所指的链表的 data 进行比较, 如果相等, 将这个结点插入到一个新链表中, 然后两个指针 cur1, cur2, 一起向后走一步,如果不相等, 就将 data 值小的那个指针向后移动, 而另外一个指针不动, 在进行比较,重复以上动作,直到 cur1 或者 cur2 两个中其中一个为空,则停止循环。


624 LinkNode* UnionSet(LinkNode* head1, LinkNode* head2)//求两个有序链表的交集;返回表示交集的新链表
625 {
626     if(head1==NULL || head2==NULL){
627         return NULL;
628     }
629      LinkNode* cur1=head1;
630      LinkNode* cur2=head2;
631      LinkNode* newhead=NULL;
632      LinkNode* newtail=NULL;
633      while(cur1!=NULL&&cur2!=NULL){
634          if(cur1->data<cur2->data){
635              cur1=cur1->next;
636          }else if(cur1->data>cur2->data){
637                  cur2=cur2->next;
638              }
639              else{
640                  //cur1->data-cur2->dat
641 
642                  if(newhead==NULL){
643                       newhead= CreateNode(cur1->data);
644                      newtail=newhead;
645                  }
646                  else{
647                      newtail->next=CreateNode(cur1->data);
648                      newtail=newtail->next;
649                  }
650                  cur1=cur1->next;
651                  cur2=cur2->next;
652              }
653          }
654          return newhead;
655 }

16、拷贝复杂链表
链表的数据结构

typedef struct ComplexNode { 
LinkType data; 
struct ComplexNode* next; 
struct ComplexNode* random; 
} ComplexNode; 

复杂链表中除了 data, next, 之外,还有一个 random, 它可能指向链表中任何一个节点, 还可能指向空。
在进行复杂链表的拷贝时, 可以采用下面的方法, 先将复杂链表按照简单链表进行复制,将其复制到一个新链表中, 此时的新链表还是一个简单链表, 然后再遍历旧链表,求出每一个节点所对应的 random 相对于头节点的偏移量, 再遍历新链表, 根据所求得的偏移量确定新链表中的 random 的指针的指向。
  

ComplexNode* CreateComplexNode(LinkNodeType value){
    ComplexNode* newnode = (ComplexNode*)malloc(sizeof(ComplexNode));
    newnode->data = value;
    newnode->random = NULL;
    newnode->next = NULL;
    return newnode;
}

size_t  Diff(ComplexNode* src, ComplexNode* dst){
    if (src == NULL || dst == NULL){
        return (size_t)-1;//无符号长整形是一个很大的数字用来表示找不到
    }
    size_t count = 0;
    while (src != NULL){
        //src跳出循环有两种情况src找到了dst,返回偏移量,src走到NULL也没找到,返回(size_t)-1
        if (src == dst){
            return count;
        }
        count++;
        src = src->next;
    }
    return (size_t)-1;
}


ComplexNode* Step(ComplexNode* pos, size_t offset){//从pos的位置走offset的位置
    if (pos == NULL){
        return NULL;
    }
    size_t i = 0;
    for (; i<offset; i++){
        pos = pos->next;
    }
    return pos;
}


ComplexNode* CopyComplex(ComplexNode* head)// 拷贝复杂链表
{
    if (head == NULL){
        return;
    }
    ComplexNode* newhead = NULL;
    ComplexNode* newtail = NULL;
    ComplexNode* cur = head;
    //复制链表
    for (; cur != NULL; cur = cur->next){
        ComplexNode* newnode = CreateComplexNode(cur->data);
        if (newnode == NULL){
            newtail = newhead = newnode;
        }
        else{
            newtail->next = CreateComplexNode(cur->data);
            newtail = newtail->next;
        }
    }
    //使cur和newcur保持同步,尽享便利
    ComplexNode* newcur = newhead;
    for (cur = head; cur != NULL && newcur != NULL; cur = cur->next, newcur = newcur->next){
        //cur到这里已经指向空了,我们必须对cur进行重置
        if (cur->random == NULL){
            newcur->random = NULL;
            continue;
        }
        size_t offset = Diff(head, cur->random);//求每个random指针修改head 的偏移步数
        newcur->random = Step(newcur, offset);//根据偏移量修改新链表的random指针的指向
    }
    return newhead;
}

方法二:

ComplexNode* CopyComplex2(ComplexNode* head){//拷贝复杂链表
    ComplexNode* cur = head;
    //遍历旧链表,给每一个节点都创建一个对应的节点,并且将这个节点插入到旧节点之后
    for (; cur != NULL; cur = cur->next->next){
        ComplexNode* newnode = CreateComplexNode(cur->data);
        newnode->next = cur->next;
        cur->next = newnode;
    }
    //遍历链表,更新每个新节点的random指针
    for (cur = head; cur != NULL; cur = cur->next->next){
        if (cur->random == NULL){
            cur->next->random = NULL;
            continue;
        }
        cur->next->random = cur->random->next;
    }
    //再遍历链表,把新节点拆下来,组装成新链表
    ComplexNode* newhead = NULL;
    ComplexNode* newtail = NULL;
    for (cur = head; cur != NULL; cur = cur->next){
        ComplexNode* to_delete = cur->next;
        cur->next = to_delete->next;
        if (newhead == NULL){
            newhead = newtail = to_delete;
        }
        else{
            newtail->next = to_delete;
            newtail = newtail->next;
        }
    }
    return newhead;

}
考研复试面试题(数据结构篇)----2020考研 以下题目笔者为了准备考研复试用的题目,在看之前,先不要看答案,看看自己会不会,这样再看答案有助有自己理解 1.Java与C++的区别: (1)JAVA中没有显式的指针,但是C++中有 (2)JAVA只能支持单继承,但是C++支持多继承(一个类可以继承多个类) (3)JAVA中有自动的垃圾回收机制,用完一个内存之后无需自己释放,但是C++需要自己delete或者free,所以可能出现内... 阅读详情

相关推荐

数据结构链队基本操作.cpp

掌握队列的链接存储结构;掌握队里的操作特性;掌握基于链队的基本操作的实现方法,并建立一个空队列;对已建立的队列进行插入、删除、取头元素等基本操作。

最佳数据结构常见面试题和答案合集

队列是一种线性结构形式,它遵循 FIFO(先进先出)方法来访问元素。Dequeue、enqueue、front、rear 是队列的基本操作。像堆栈一样,队列可以使用数组和链表来实现。在堆栈中,最近添加的项目首先被删除。与此相反,在队列的情况下,首先删除最近最少添加的项目。

不定时分享最优质的网络技术与教程,满满的干货。 4407

vmware虚机Debian10磁盘空间无损扩容

该方法不适和LVM的磁盘管理 备份 一定要先做备份,虚机中直接创建一个快照备份 vm上增加空间 初始给的40G空间不够需要扩容,vm那给系统添加到100G 重新分区 查看当前分区情况 sudo fdisk -l

lms99251的博客 7455

保研面试 算法题_计算机考研/保研复试重点整理-数据结构篇

先来一个知识框架图,前方高能预警好了,看完这个框架,你慌了吗?大家心里有个数之后,我们开始划重点,都去给我背!一、什么是数据结构?数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。结构包括逻辑结构和物理结构。数据的逻辑结构包括4种,(1)集合:数据元素之间除了有相同的数据类型再没有其他的关系 (2)线性结构:数据元素之间是一对一的关系 (3)树形结构...

weixin_39644915的博客 1949

《大明王朝1566》中,朝廷财政危机无法解决的根源分析

财政困局中的财富最终流向三重黑洞:​皇室挥霍​(如嘉靖炼丹修殿)、特权阶层贪腐​(严党年入百万两盐税)、制度性损耗​(宗室供养、低效官僚)。更深层的“钱”其实是被禁锢在道德化治理的牢笼中——当国家用“黄河长江皆可为用”的权术思维替代制度性改革时,财政危机便成为帝制王朝无法逃脱的宿命。

为了小家奋斗 1973

LC整流滤波电路DIY:电感电容配合,手把手搭建低纹波直流电源

在直流电源设计中,整流滤波是连接交流输入与稳定输出的关键环节。常见的电容滤波虽然简单,但在大负载下纹波抑制能力有限,电感抵抗电流突变、电容抵抗电压突变,二者组合构成的LC滤波能有效降低输出电压纹波,同时减小开机浪涌电流。在工频线性电源、功放电源等对噪声敏感的场景中,LC滤波常作为稳压前的平滑缓冲。本文以一套完整DIY项目为线索,介绍整流桥后串联功率电感、并联滤波电容的电路构成,结合实际计算与波形测试,讨论电感量估算、电容选取、谐振风险、饱和电流等工程问题,并给出上电测试和故障排查方法。通过搭建与调试,可直观

weixin_29168813的博客 378

数据结构面试题整理

1.你熟悉什么数据结构? 数组 链表 栈 队列 哈希 二叉树 二叉查找树 二叉堆 b树 b+树 2.快排?快排的实现过程?复杂度如何? 方式~双边 单边 复杂度~nlogn 单边过程~ 1-先找到一个基准元素,起始下标 2-遍历,如果元素比基准元素小,下边+1 此元素与下标对应元素交换位置 3-当遍历完后,基准元素与当前下标元素交换位置,此时基准元素就分成了两组数据 4-两边的数据在递...

weixin_44655181的博客 4720

2024高教社杯数学建模国赛B题丨国一原创论文解析及源码超详细分享!

继续分享一篇2024国赛B题的国奖论文,包含可运行源代码jupyter,国赛B题通常比较聚焦实际复杂系统的多目标优化决策,主要偏重算法实现与概率建模解决开放性的管理问题。而且高度开放,无标准答案,学科交叉复杂,如资源调度、交通优化、海洋探测等。比较建议有一定统计学基础的同学参加。

ihui永不放弃 6739

10道经典链表面试题

目录 1.删除链表中等于给定值val的所有节点 2.反转一个单链表 3.给定一个带有头结点head的非空单链表,返回链表的中间结点。如果有两个中间结点,则 返回第二个中间结点 4.输入一个链表,输出该链表中倒数第k个结点 5.将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所 有节点组成的 6. 编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的 结点之前 7. 链表的回文结构 8. 输入两个链表,找出它们.........

xaiobit_hl的博客 4287

实验手册(灾难恢复)

我们发现DC1与DC2的复制出现问题,此时我们检查了在DC2中,DC1是否被正确注册。这里选择还原系统状态,因为我们原DC1上只备份了AD的数据,所以我们在新的这台服务器上还原的也是AD数据库。因为我们是单域下的测试,只测试了一个域,所以它会出现这样的报错。我们选择远程共享文件夹,我们备份的时候,是在备份这台服务器上的。同时删除SRV记录,A记录,NS记录,SOA记录,框框里面的所有有关dc1的记录全部删除。如果在企业中AD数据的备份是每周或者每月都会有一次备份,选择恢复AD数据库的时间。

weixin_52364868的博客 1310

Pythia: A Customizable Hardware Prefetching Framework Using Online Reinforcement Learning——“预取”论文解读

参考传送门: 1. Hardware Prefetching笔记 2. 全球百科——缓存预取 3. 百度百科——缓存数据预期技术 目录0. 什么是Hardware Prefetching(本节内容不包括在论文中)1. 简介1.1 关于Hardware Prefetching的一些关键信息1.2 现阶段方法的缺陷1.3 论文团队的目标1.4 核心思想2. 必要的背景知识介绍2.1 强化学习(Reinforcement learning)2.2 为什么说强化学习是一个好的解决思路3. 解决方法与思路3.1 Py

Pinkgranite86的博客 2168

Java数据结构-单链表相关的面试题

第一题,求单链表中有效节点的个数 第二题,查找单链表中倒数第K个结点 第三题,单链表的反转 第四题,从尾到头打印单链表 package com.spx.list; import java.util.Stack; public class SingleLinkedListDemo { public static void main(String[] args) { // TODO Auto-generated method stub // 测试一下 // 先创建几个节点 Her.

m0_48792508的博客 271

PLC的自抗扰控制(ADRC)算法

1、自抗扰控制算法,网上很多文章有所讲解,大家也可以关注韩京清教授的论文和书籍,这里就不赘述了,下面给出梯形图+SCL代码。 1、跟踪微分器 2、线性控制率 3、博图SCL控制代码 4、ADRC控制算法的所有公式汇总 ......

RXXW_Dor的博客 3853

数据结构与算法--单链表相关面试题

此文章仅作为自己学习过程中的记录和总结,同时会有意地去用英文来做笔记,一些术语的英译不太准确,内容如有错漏也请多指教,谢谢! 一、概述 获取单链表的有效元素个数【新浪面试题1】 获取单链表倒数第k个结点【新浪面试题2】 反转单链表【腾讯面试题】 从尾到头打印单链表【百度面试题】 合并两个有序的单链表,合并之后的链表依然有序 此文章会根据以上五个问题分别给出实现代码,以及一些注意事项。在文末会给出检测代码。 (关于属性、构造器、结点结构及基本方法,具体可见:数据结构与算法–单链表(Single Link

ZZay's 423

主流几个JDK版本:JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

主流几个JDK版本:JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

技术分享 1725

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

数据结构:单链表相关面试题

单链表基本功能实现: https://blog.youkuaiyun.com/W_J_F_/article/details/80007864 ListNode.h // 逆序打印单链表 void PrintSListFromTail(pNode pHead); // 删除链表的非尾结点,要求:不能遍历链表 void DeleteListNotTailNode(pNode *pHead, pNod...

W_J_F_的博客 321

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

数据结构-单链表相关面试题

从尾到头打印单链表我们在学习递归时,曾经遇到过这样一道题目,打出1234的每一位数,那么我们用递归的思想是:打印1234,就要打出123+4,接下来是12+3+4,在然后1+2+3+4,就能打印每一位数,显然是将一个复杂问题拆解为一个个小问题。 那么同理逆序打印单链表也是,先打最后一个然后以此类推。直接上代码。void LinkListReversePrint(LinkNode* head) {

mxrrr_sunshine的博客 397

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Java尚硅谷数据结构与算法学习记录(3)续-单链表相关面试题

单链表 面试题 求单链表有效节点的个数: public static int getLength(HeroNode head){ if(head.next==null){ return 0; } int length=0; HeroNode cur=head.next; while(cu...

qq_38715538的博客 302

尚硅谷Java数据结构与算法——021单链表新浪面试题

求单链表中有效节点的个数。 //方法:获取到单链表的节点的个数(如果是带头结点的链表,需求不统计头节点) /** * * @param head 链表的头节点 * @return 返回的就是有效节点的个数 */ public static int getLength(HeroNode head) { // 判断是否为空。 if (head.next == null) { return 0; .

qq_33790600的博客 183

单链表及相关面试题

#pragma once       #includestdio.h>   #includeassert.h>   #includemalloc.h>   #includestdlib.h>       typedef int DataType;

wangneng691811457的博客 319

数据结构与算法——单链表

链表 小结上图: 链表是以节点的方式来存储, 是链式存储 每个节点包含 data 域, next 域:指向下一个节点. 如图:发现 链表的各个节点不一定是连续存储. 链表分 带头节点的链表和 没有头节点的链表,根据实际的需求来确定 单链表 单链表看似连续 但是并不是 这只是逻辑结构 不考虑排名 过程: 添加(创建) 1.先创建一个head头节点,作用就是表示单链表的头 2.后面我们每添加一个节点,就直接加入到链表的最后遍历: 3.通过一个辅助变量,帮助遍历整个链表 //小的知识点: 1.在

三横同学的博客 797

Java 数据结构——单链表面试题(三)

长度为奇数的链表 1.找到中间节点 2.反转链表 3.val 值相等,分别向后走 长度为偶数的链表

rain67的博客 771

数据结构-单链表(Java实现)

单链表 一种链式存储的数据结构,链表中的数据是由元素+指针构成,从头结点开始依次指向后面的每一位 ​ 可以在内存中就直接能够排序数据 ​ 比如在业务中,如果给你一堆无序id的数据,就可以直接用单例表中的有序排列让数据按顺序排起来 package singlelinkedlist; /* @CreateTime 2021/9/6 10:44 @CreateBy cfk */ public class SingleLinkedListDemo { public

weixin_51951233的博客 241

【数据结构与算法之面试题】线性结构类面试题

【数据结构与算法之面试题】线性结构类面试题

代码改变世界 306

【C++上岸】C++常见面试题目--数据结构篇(第十四期)

恭喜你完成本期数据结构篇的学习!🎉 这些题目覆盖了链表、树、搜索等核心内容,多加练习一定能掌握。如果在面试中遇到类似问题,记得先理清思路再编码哦~有问题欢迎在评论区留言,我会尽力解答。下期再见!😊练习建议手写代码加深记忆。尝试优化空间或时间复杂度。刷题平台推荐:LeetCode或牛客网。保持热情,C++上岸不是梦!💪。

一起学习进步吧 1140

java 双向链表_链表:众多数据结构的基石

导读:本文主要介绍为什么需要链表、链表的定义、链表用 Java 实现、链表和数组的对比、链表最常见的面试题​我们之前学习数组时讲过,数组和链表是众多高级数据结构实现的基石,哈希表、二叉树等数据结构都是基于数组和链表实现的。之前我们已经学习过了最基础的数据结构数组(数组:最基础的数据结构),今天我们来学习数据结构中的另一块基石:链表。之前我们学习数组时说过,数组是用一组连续的内存空间存储数据。现在假...

weixin_39948824的博客 79
上一篇: vim的配置
下一篇: open/read/write/close等文件相关系统调用接口
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值