环境:win10,codeblocks
最近跟着本科生一起学习下数据结构,把解答的一些问题push上来。由于本人很久很久没使用过C语言,被指针弄的头痛,所以有些解题思路比较绕不是因为蠢。而是程序的莫名报错,不断换方法AC的结果。
- 题一,将两个非递减的有序链表合为一个非递减的有序链表(要求利用原来两个链表的存储空间,不另外占用其他空间,表中不允许有重复数据)
- 算法思路:本来是想在一个函数中将链表2依次插入到链表1中去的,然后各种情况需要考虑,然后简单起见。编写了一个insertNode(linkList* head,linkList* item)函数,然后就将链表2中的节点依次插入就行了。
- 考虑的情况:因为不能使用额外的空间,不是很多人使用数组或者神马的来存储,你会遇到相应的问题。比如你将链表2插入到链表1,如果链表2的第一个元素比链表1小怎么办,那就涉及到表头插入,如果链表2的元素都比链表1的第一个小怎么办等等问题。为了编程的可重用性,编写一个插入函数是有必要的。
- 废话不多说直接贴代码:(程序核心代码其实并不多,只是博主有强迫症,喜欢把每个细节都写好.这样子新手看起来就容易点,起来可以直接跑起来,如果跑不起肯定是我在优快云上传删注释的时候弄坏了…源文件的注释更多..而且一个文件里用了多个方法,直接po上来会晕掉去的..)
#include<stdio.h>
#include<stdlib.h>
//定义节点
typedef struct node{
int data;
struct node *next;
}linkList;
//构造链表
linkList* createLinkedList(linkList* head)
{
int data[5];//为方便操作定义一个大小为5的链表
int i = 0;
linkList* cur = head;//定义一个cur当前节点来遍历整个链表
while(i < 5)
{
linkList *temp = (linkList*)malloc(sizeof(linkList));//定义一个temp节点来存储输入数据
scanf("%d",&data[i]);
temp->data = data[i];//临时节点保存数据
temp->next = NULL;
cur->next = temp;//遍历指针指向临时节点
cur = temp;//向后移一位
i++;
}
return head;
}
//插入节点函数
linkList* insertNode(linkList* head,linkList* item)
{
linkList* cur = head->next;//cur指向链表头结点后的元素
linkList* pre =NULL;//pre始终在cur的前面,因为插入有一种情况就是在pre和cur之间插入的
while(cur->data <= item->data && cur!=NULL)//在当前的值比item小时进入while循环
{
if(cur->next == NULL)//意味链表到最后了,这时候又满足比item->data小,则可以把item插入到最后一个
{
cur->next = item;
return head;//直接返回head节点,函数结束
}
pre = cur;//保存cur当前点
cur = cur->next;//cur指向下一个节点
}
//如果经过了上述的while循环,cur的位置没变,说明item->data比head->next->data还小,所以插入在head和cur之间。
if(cur == head->next)
{
item->next = cur;
head->next = item;
return head;//返回head,结束函数
}
pre->next = item;//正常情况,在pre和cur之间插入item
item->next = cur;
return head;//返回head,结束函数
}
linkList* sortLinkedList(linkList* head1,linkList* head2)
{
//萌新博主之所以下面的指针声明如此浩大,是因为这几天被没malloc地址的野指针给玩坏了,程序各种异常。。
linkList* head = (linkList*)malloc(sizeof(linkList));
linkList* cur = (linkList*)malloc(sizeof(linkList));
linkList* newLink = (linkList*)malloc(sizeof(linkList));
linkList* pre = (linkList*)malloc(sizeof(linkList));
linkList* print = (linkList*)malloc(sizeof(linkList));
//简单的判断,不做无谓的牺牲
if(head1 == NULL)
{
return head2;
}
else if(head2 ==NULL)
{
return head1;
}
head = head1->next;//指向链表1的头结点后的第一个节点
cur = head2->next;//同上
while(cur != NULL)
{
pre = cur->next;//保留cur的下一个节点,发现单词用错了。。应该用next的。。你们懂就行
//下面的语句也许你会觉得加起来很傻X,是有用意的,即把每一个节点跟后面断开。不断开会在某些情况出问题的
cur->next = NULL; //跟下一个节点断开
newLink = insertNode(head1,cur);//直接调用,插入cur节点
//下面来打印以下每次插入后的结果,建议萌新多写printf来打印结果,然后在纸上慢慢分析错误。
print = newLink->next;
while(print != NULL)
{
printf("%d->\t",print->data);
print = print->next;
}
cur = pre;//cur指向下一个
head1 = newLink;//更新head1
}
return newLink;
}
int main()
{
linkList *head1 = (linkList*)malloc(sizeof(linkList));
linkList *head2 = (linkList*)malloc(sizeof(linkList));
linkList *link1 = createLinkedList(head1);
linkList *link2 = createLinkedList(head2);
linkList *print1 = link1->next;
linkList *print2 = link2->next;
while(print1 != NULL)
{
printf("%d->\t",print1->data);
print1 = print1->next;
}
while(print2 != NULL)
{
printf("%d->\t",print2->data);
print2 = print2->next;
}
linkList *newLink = sortLinkedList(link1,link2);
linkList *print = newLink->next;
while(print != NULL)
{
printf("%d\t",print->data);
print = print->next;
}
return 0;
}