0
点赞
收藏
分享

微信扫一扫

C语言(三)

m逆光生长 2022-03-11 阅读 69

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:直接在链上进行逆转,设置三个工作指针,每次操作先通过第三个指针记录后续链表,再将第一个指针和第二个指针逆转。

总结:今日练习了几道链表题,学习了头插法和尾插法以及工作指针的设置思想。明日继续链表的学习。

举报

相关推荐

0 条评论