对于大量数据的插入和查找,我们应该如何选择数据结构呢?
思路:
我们知道链表插入快,但是查找慢,map查找快,但是无序,想要有序的查找和插入,那就把两者结合起来使用。
链表:手写一些函数对链表进行基本的插入和删除,每次插入完成后需要更新map。
map: map用来保存每个插入点的指针,用map查找插入点的指针,然后直接插入。map的各种操作的时间复杂度都是O(lgN)。
插入函数:
struct Node* inserter(struct Node *p,int key,int i) //把key插入到的前面 ,0插入到p的前,1后
{
struct Node *now;
now=(struct Node*)malloc(sizeof(struct Node));
now->data=key;
if(i==0) //插入到前面
{
now->prime=p->prime;
p->prime->next=now;
now->next=p;
p->prime=now;
return now;
}
else
{
now->prime=p;
now->next=p->next;
if(p->next!=NULL)
p->next->prime=now;
p->next=now;
return now;
}
//返回的now指针用来更新map
}
返回的now指针用来更新map
map:
#include<map> //记得加头文件
map<int,struct Node*> m;
struct Node *head,*now,*next;
head=(struct Node*)malloc(sizeof(struct Node));
head->prime=NULL;
head->data=-1;
now=(struct Node*)malloc(sizeof(struct Node));//第一个
head->next=now;
now->next=NULL;
now->data=1;
now->prime=head;
m[1]=now; //把第一个数的指针保存
AC代码(后面有更好的思路):
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<map>
#define Max 100010
#define max(a,b) a>b?a:b;
#define min(a,b) a>b?b:a;
using namespace std;
int live[Max]; //记录是否被删除
struct Node{
int data;
struct Node* next;
struct Node* prime;
};
struct Node* inserter(struct Node *p,int key,int i) //把key插入到的前面 ,0前,1后
{
struct Node *now;
now=(struct Node*)malloc(sizeof(struct Node));
now->data=key;
if(i==0) //插入到前面
{
now->prime=p->prime;
p->prime->next=now;
now->next=p;
p->prime=now;
return now;
}
else
{
now->prime=p;
now->next=p->next;
if(p->next!=NULL)
p->next->prime=now;
p->next=now;
return now;
}
}
void show(struct Node *q) //显示还有表内的人
{
struct Node *p=q;
p=p->next;
while(p!=NULL) //输出格式 ,空格
{
if(!live[p->data])
{
printf("%d",p->data); //最后记得调整格式问题
break;
}
p=p->next;
}
p=p->next;
while(p!=NULL)
{
if(!live[p->data])
{
printf(" %d",p->data); //最后记得调整格式问题
}
p=p->next;
}
printf("\n");
}
int main()
{
map<int,struct Node*> m;
struct Node *head,*now,*next;
head=(struct Node*)malloc(sizeof(struct Node));
head->prime=NULL;
head->data=-1;
now=(struct Node*)malloc(sizeof(struct Node));//第一个
head->next=now;
now->next=NULL;
now->data=1;
now->prime=head;
m[1]=now; //第一个
int num,j,n,M;
scanf("%d",&n);
for(int i=2;i<=n;i++)
{
scanf("%d%d",&num,&j);
now=m[num];//要插入的地方
m[i]=inserter(now,i,j);
}
scanf("%d",&M);
memset(live,0,sizeof(live));
for(int i=0;i<M;i++)
{
scanf("%d",&num);
live[num]=1;//需要删除的同学
}
show(head);
return 0;
}
(辛苦的写完代码后,发现有些时候可以只用线性表就能完成快速的查找.....)
当插入的数据类型为整型的时候,我们用如下结构体来保存数据:
struct Node{
int data;
int prime; //指向前面一个数的位置
int next; //指向后面一个数的位置
}node[100010];
我们可以直接利用节点的数据,达到直接访问下一个节点,每次插入完成后像链表一样调整前面数据就好,查找、插入的时间复杂度都是O(1)。