链表
讨论链表之前先看一个数组模拟的链表
struct s
{
Int v;
Int next;
}a[1000];
其中v就是值,而next是下一个值所存储的位置的下标
如果存在一条链是a[0]->a[4]->a[2]
那么a[0].next=4,a[4].next=2
而真正的链表与上面的区别就是可以动态开空间,因为数组的大小是直接开好的,所以容易出现浪费
struct s
{
int v;
s *next;
};
其中v存这个点的值,next是下一个值所存储的位置的地址
然后就是如何定义了,由于每个点都是用的时候才开辟,所以就用指针来存储地址即可
Struct s *p;
动态开辟地址可以用malloc,new(据说区别是占用空间不一样,我只会malloc)
p=(struct s *)malloc(sizeof(s));
这样p就指向了一个新定义的结构体
接下来就是如何创建链表了
首先链表开始分为头结点和头指针
头指针存储的就是第一个点的地址
头结点是在第一个点之前定义了一个结构体,这个结构体的next才是第一个节点的地址
而他的值域v通常存储有多少个节点
插入一般分为两种方式
头插法,尾插法(我比较喜欢头插法)
头插法
每次把新的点放在开头,只需要把本个节点的next指向第一个节点,然后本个节点就可以当做第一个节点了
尾插法
需要一直记录最后一个点在哪里,插入的时候,把最后一个节点的next指向本个节点即可
一般来说最后一个节点的next都要存NULL
所以遍历的时候只需要while(p!=NULL)一直循环即可
有个比较有锻炼的题,可以试试
有一个链表,其中奇数位置取出来单调递增,偶数位置取出来单调递减(可以自己建立,奇数是i,偶数是n-i),让你把整个链表变成单调递增的
#include<stdio.h> #include<malloc.h> #include<algorithm> using namespace std; struct s { int v; s *next; }; void create(s *p,int n) { for(int i=1; i<=n; i++) { p->next=(struct s*)malloc(sizeof(s)); p=p->next; p->next=NULL; if(i%2) p->v=i; else p->v=n-i; } } void print(s *p) { while(p!=NULL) { printf("%d\n",p->v); p=p->next; } printf("---------------------------------------\n"); } int main() { int n; scanf("%d",&n); s *head,*p; head=(struct s*)malloc(sizeof(s)); head->v=n; head->next=NULL; create(head,n); printf("输出原始链表\n"); print(head->next); s *head1=NULL,*head2=NULL,*p1,*p2; p=head->next; int z=1; while(p!=NULL) { if(z) { if(head1==NULL) head1=p; else p1->next=p; p1=p; p=p->next; p1->next=NULL; } else { if(head2==NULL) head2=p; else p2->next=p; p2=p; p=p->next; p2->next=NULL; } z^=1; } printf("分别输出两个链表\n"); print(head1); print(head2); p2=head2->next; head2->next=NULL; while(p2!=NULL) { p=p2; p2=p2->next; p->next=head2; head2=p; } printf("输出翻转后的2链表\n"); print(head2); s *head3=NULL; while(head1!=NULL||head2!=NULL) { if(head2==NULL||(head1!=NULL&&head1->v<head2->v)) { if(head3==NULL) head3=head1; else p->next=head1; p=head1; head1=head1->next; } else { if(head3==NULL) head3=head2; else p->next=head2; p=head2; head2=head2->next; } } printf("输出合并以后的链表\n"); print(head3); }
做法就是
先根据奇数偶数位置,把链表拆成两个
然后把偶数位置反转过来(把这个链表一直头插到一个空的链表就反转成功了)
然后每次都取两个链表当前没取过,且最小的尾插到答案的链表中即可