链表---详解

链表

链表不一定由结构体构成,也可能是数与数之间的固定指向
一般来说,有头链表使用时更方便
无头链表 代码演示:
#include <iostream>
#include <map>
#include <ctime>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <unordered_map>
#include <stack>
using namespace std;
#define DIGIT_LEN 3
typedef struct Node {
        int data;
       Node* next;
}Node;
Node* getNewNode( int val) {
       Node* p = (Node*)malloc( sizeof (Node));
       p->data = val;
       p->next = NULL;
        return p;
}
void clear(Node* head) {
        if (head == NULL) return ;
        for (Node* p = head, *q; p; p = q) {
              q = p->next;
              free(p);
       }
        return ;
}
Node* insert(Node* head, int pos, int val) {
        if (pos == 0) {
              Node* p = getNewNode(val);
              p->next = head;
               return p;
       }
       Node* p = head;
        for ( int i = 0; i < pos - 1; i++) {
              p=p->next;
       }
       Node* node = getNewNode(val);
       node->next = p->next;
       p->next = node;
        return   head;
}
Node* erase(Node* head, int pos) {
       Node* p = head;
        if (pos == 0) {
              head->data = 0;
              head = head->next;
              p->next = NULL;
               return head;
       }
        for ( int i = 0; i < pos - 1; i++)
       {
              p = p->next;
       }
       p = p->next->next;
        return head;
}
void output_linklist(Node *head, int flag=0) {
        int   n = 0;
        for (Node* p = head; p; p = p->next) {
              ++n;
       }
        for ( int i = 0; i < n; i++) {
              printf( "%3d" , i);
              printf( "  " );
       }
       printf( "\n" );
        for (Node* p = head; p; p = p->next) {
              printf( "%3d" , p->data);
               if (p->next)printf( "->" );
       }
        if (flag == 0)printf( "\n\n\n" );
        else printf( "\n" );
        return ;
}
int find(Node* head, int val) {
       Node* p = head;
        int n = 0;
        while (p) {
               if (p->data == val)
              {
                      output_linklist(head,1);
                       for ( int i = 0; i < n; i++)
                             printf( "     " );
                      printf( "  ^  \n" );
                       for ( int i = 0; i < n; i++)
                             printf( "     " );
                      printf( "  |  \n" );
                       return 1;
              }
              n += 1;
              p = p->next;
       }
        return 0;
}
int main()
{
       srand(( unsigned int )time(0));
    #define MAX_OP 20
       Node* head = NULL;
        for ( int i = 0; i < MAX_OP; i++) {
               int pos = rand() % (i + 1), val = rand() % 100;
              printf( "insert %d at %d to linklist\n" , val, pos);
              head=insert(head, pos, val);
              output_linklist(head);
       }
        int val;
        while (~scanf_s( "%d" , &val)) {
               if (!find(head, val)) {
                      printf( "not found\n" );
              }
       }
       clear(head);
        return 0;
}
有头节点运用于插入--减少了if
Node * insert( Node * head , int pos , int val ) {
        Node new_head, * p = &new_head, * node = getNewNode( val );//临时创建头节点
       new_head.next = head ;
        for ( int i = 0; i < pos ; i++) p = p->next;
       node->next = p->next;
       p->next = node;
        return new_head.next;
}
循环链表
特点:
  • 把链表的尾节点当作虚拟头节点
  • 通过快慢指针可以分辨是单向链表还是循环链表
代码:哈希
bool hasCycle(ListNode *head) {
        unordered_map<ListNode*,int> umap;
        ListNode *p=head;
        while(p){
            umap[p]++;
            if(umap[p]==2return true;
            p=p->next;
        }
        return false;
    }
快慢指针
bool hasCycle (ListNode *head) {
    ListNode *fast_ptr=head;
    ListNode *low_ptr=head; 
    while (fast_ptr&&fast_ptr->next){
        low_ptr=low_ptr->next;
        fast_ptr=fast_ptr->next->next; 
        if (low_ptr==fast_ptr) return true ;
    } 
    return false ;
}
  • 双指针等距移动法:确定链表中的倒数第几位的位置
leetcode:19
双向链表
  • 17
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值