1、逆序数据建立链表
本题要求实现一个函数,按输入数据的逆序建立一个链表。
#include <stdio.h>
#include <stdlib.h>
struct ListNode {
int data;
struct ListNode *next;
};
struct ListNode *createlist();
int main()
{
struct ListNode *p, *head = NULL;
head=createlist();
for (p=head;p!= NULL;p=p->next)
printf("%d ", p->data);
printf("\n");
return 0;
}
struct ListNode *createlist()//不带头结点的头插法
{
struct ListNode *head=NULL, *p=NULL;
int data;
scanf("%d", &data);
while (data!=-1)//-1为链表结束标志
{
p=(struct ListNode*)malloc(sizeof(struct ListNode));
p->data=data;
p->next=head;//当前结点插到首结点前
head=p;//首结点前移
scanf("%d", &data);
}
return head;
}
输入:
1 2 3 4 5 6 -1
输出:
6 5 4 3 2 1
ps:一般创建链表时采用两种方法,即头插法和尾插法,按照头插法创建的链表,其链表结点顺序和输入顺序相反;按照尾插法创建的链表,其链表结点顺序和输入顺序相同。因此想要逆序数据建立链表可直接采用头插法,在此采用了无头结点的头插法,将每个新结点插入到当前链表首结点之前。
2、链表拼接
本题要求实现一个合并两个有序链表的简单函数。
#include <stdio.h>
#include <stdlib.h>
struct ListNode {
int data;
struct ListNode *next;
};
struct ListNode *createlist(); /*裁判实现,细节不表*/
struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2);
void printlist( struct ListNode *head )//打印数据
{
struct ListNode *p = head;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
struct ListNode *list1, *list2;
list1 = createlist();
list2 = createlist();
list1 = mergelists(list1, list2);
printlist(list1);
return 0;
}
struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2)
{
struct ListNode *list=(struct ListNode *)malloc(sizeof(struct ListNode)),*head=NULL;
head=list;
while(list1&&list2){
if(list1->data<=list2->data){//list1的结点较小时,插入list新链表中
list->next=list1;
list1=list1->next;//list1的遍历指针往后走
list=list->next;//list指针往后走,保持指向尾结点
}
else{//list2的结点较小,选择list2插入list新链表
list->next=list2;
list2=list2->next;
list=list->next;
}
}
/* 当有一条链表遍历完成时,将另外一条链表剩下部分添加至新链表后*/
if(list1){
list->next=list1;
}
if(list2){
list->next=list2;
}
return head->next;
}
输入:
1 2 5 -1
2 3 4 6 -1
输出:
1 2 3 4 5 6
ps:本题构造一条带头结点的新链表(不带头结点的话操作会麻烦一点,需要在开头提取两个链表的第一个结点,指明新链表头指针的指向后才进入while循环通过尾插法插入被选取的结点),然后遍历两条待合并链表,依次选取合适的结点插入新链表中。另外还有种方法是直接选择一条链表作为合并链表,将另外一条待合并链表的结点依次选取合适的位置插入其中。
3、链表逆置
本题要求实现一个函数,将给定单向链表逆置,即表头置为表尾,表尾置为表头。
#include <stdio.h>
#include <stdlib.h>
struct ListNode {
int data;
struct ListNode *next;
};
struct ListNode *createlist(); /*裁判实现,细节不表*/
struct ListNode *reverse( struct ListNode *head );
void printlist( struct ListNode *head )
{
struct ListNode *p = head;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
struct ListNode *head;
head = createlist();
head = reverse(head);
printlist(head);
return 0;
}
struct ListNode *reverse( struct ListNode *head )
{
struct ListNode *p1=NULL,*p2=head,*p3;//p1为前一个结点,p2为后一个结点
while (p2) {//将从p1->p2转变为p2->p1
p3=p2->Next;//记录p2后一个结点
p2->Next=p1;//逆转
p1=p2;
p2=p3;
}
return p1;
}
输入:
1 2 3 4 5 -1
输出:
5 4 3 2 1
ps:直接在链上进行逆转,设置三个工作指针,每次操作先通过第三个指针记录后续链表,再将第一个指针和第二个指针逆转。
总结:今日练习了几道链表题,学习了头插法和尾插法以及工作指针的设置思想。明日继续链表的学习。