视频编程作业-两个有序列表的合并
2016-09-25 20:39
393 查看
算是写了快要一天才写出来的一个题!!有些崩溃啊~
本题要求实现一个函数,将两个链表表示的递增整数序列合并为一个递>增的整数序列。
函数接口定义:
其中List结构定义如下:
L1和L2是给定的带头结点的单链表,其结点存储的数据是递增有序的;函数Merge要将L1和L2合并为一个递增的整数序列。应直接使用原序列中的结点,返回归并后的链表头指针。
裁判测试程序样例:
输入样例:
3
1 3 5
5
2 4 6 8 10
输出样例:
1 2 3 4 5 6 8 10
NULL
NULL
注:不想看废话看粗体字
一拿到这个题目的时候就有思路了,无非就是比较L1->Data和L2->Data,然后往L上接。
不想重写一些链表的操作,就想着拿之前写的链表的基本操作的代码过来用吧,然后问题就暴露出来了。当时写“按位插入”操作的时候的确是实现了,却没有深入的理解,用到这个题目上,不理解好根本就是用不上的了。(这个题目不需要按位插入,我只是偷懒没有重写新的插入操作(直接链表尾部插入)。)
然后我就开始去好好想,好好理解了。最后也理解了~这里得到一个启示啊,遇到问题一定要赶紧解决,否则总有会因为当时没能解决问题而无法解决手下的问题这种情况,这时候就尴尬了。
之后呢,在编码的过程中,发现了题目里面的几个关键词,这非常重要:L1和L2是给定的带头结点的单链表、应直接使用原序列中的结点。尤其是第二点,尤为重要!
第一点注意一下就OK了,第二点让我想了一个上午。
第二点的意思其实“是要求你把原链表上的结点一个一个摘下来,挂到新链表上。”–姥姥原话。
先看看下面两个函数:
<
bef7
p>这两个函数中,第一个可以改变传进去的实参L,即L在经过这个函数之后会变成NULL;而第二个却不能,即L在经过这个函数之后是不变的。
能看懂吗?(注:只是讨论实参L的前后变化)
虽然这两个函数都是我自己写的,但是事后我仔细想后,又有一些问题困惑了我,所以我先讲一下这两个函数对实参L的作用。
要说这两个函数,先说一下变量的存储。其实呢,在我的理解里面,指针是这样的一个东西:
这个东西这么理解:L:0x2000表示指针L这个变量名存放的地址,而0x6666才是指针变量里面的内容,这个内容存在0x5000这个内存单元中,也就是指针L是指向0x5000这个地址单元的,而这个单元恰好也是个指针,指向地址为0x6666的这个内存地址单元。 也可以这么理解:x=5;这个式子的表示图是这样的:
这个式子中x就像指针L,它们都只是变量名,只是对应地址单元的一个Nickname而已,这个x变量名存在0x6000这个地址单元中,x的值5存在0x8888这个单元。
好了,下面开始讲这两个函数:
首先,抓住理解这两个函数区别的关键:在C语言中,调用某个函数,传递过去的实参的副本,即参数是按值传递的。
第二个函数是经典的 p = p->next 型,意思不用解释了。那么,按照上面对变量存储的解释,将指针L当作实参传递过去的话,传过取得应该是0x6666这个值,在这里,L只是0x6666这个值的一个Nickname。因为L = L->Next 这个语句没有改变L这个链表任何一个 Next 域里面的内容,所以对实参L是不会有任何改变的;
再来看第一个函数。第一个函数就不同了,它通过temp变量多次修改了头结点的Next域的值,也就是对应于上面的变量存储0x6666这个值。比如说把这个值改成了0x5555,是不是就改变了头结点所指向的内存单元了?^_^ 后面的结点就不用说,跟着就连不上了。所以最后头结点指向了实参L的最后一个结点的Next域–NULL。
代码比较繁琐,Merge()函数几乎每个if/else都写了很多重复的代码,代码优化的时候提出来就好,我这么写只是为了加深那种把结点“摘下来”的思想。
THE END.
题目描述
02-线性结构1 两个有序链表序列的合并 (15分)本题要求实现一个函数,将两个链表表示的递增整数序列合并为一个递>增的整数序列。
函数接口定义:
List Merge( List L1, List L2 );
其中List结构定义如下:
typedef struct Node *PtrToNode; struct Node { ElementType Data; /* 存储结点数据 */ PtrToNode Next; /* 指向下一个结点的指针 */ }; typedef PtrToNode List; /* 定义单链表类型 */
L1和L2是给定的带头结点的单链表,其结点存储的数据是递增有序的;函数Merge要将L1和L2合并为一个递增的整数序列。应直接使用原序列中的结点,返回归并后的链表头指针。
裁判测试程序样例:
#include <stdio.h> #include <stdlib.h> typedef int ElementType; typedef struct Node *PtrToNode; struct Node { ElementType Data; PtrToNode Next; }; typedef PtrToNode List; List Read(); /* 细节在此不表 */ void Print( List L ); /* 细节在此不表;空链表将输出NULL */ List Merge( List L1, List L2 ); int main() { List L1, L2, L; L1 = Read(); L2 = Read(); L = Merge(L1, L2); Print(L); Print(L1); Print(L2); return 0; } /* 你的代码将被嵌在这里 */
输入样例:
3
1 3 5
5
2 4 6 8 10
输出样例:
1 2 3 4 5 6 8 10
NULL
NULL
注:不想看废话看粗体字
一拿到这个题目的时候就有思路了,无非就是比较L1->Data和L2->Data,然后往L上接。
不想重写一些链表的操作,就想着拿之前写的链表的基本操作的代码过来用吧,然后问题就暴露出来了。当时写“按位插入”操作的时候的确是实现了,却没有深入的理解,用到这个题目上,不理解好根本就是用不上的了。(这个题目不需要按位插入,我只是偷懒没有重写新的插入操作(直接链表尾部插入)。)
然后我就开始去好好想,好好理解了。最后也理解了~这里得到一个启示啊,遇到问题一定要赶紧解决,否则总有会因为当时没能解决问题而无法解决手下的问题这种情况,这时候就尴尬了。
之后呢,在编码的过程中,发现了题目里面的几个关键词,这非常重要:L1和L2是给定的带头结点的单链表、应直接使用原序列中的结点。尤其是第二点,尤为重要!
第一点注意一下就OK了,第二点让我想了一个上午。
第二点的意思其实“是要求你把原链表上的结点一个一个摘下来,挂到新链表上。”–姥姥原话。
先看看下面两个函数:
List Test(List L){ List temp,LL; temp = L; LL = (List)malloc(sizeof(struct Node)); L = L->Next; LL->Next = L; while( L ){ temp->Next = L->Next; L = L->Next; } return LL; } void Test2(List L){ while( L ){ L = L->Next; } }
<
bef7
p>这两个函数中,第一个可以改变传进去的实参L,即L在经过这个函数之后会变成NULL;而第二个却不能,即L在经过这个函数之后是不变的。
能看懂吗?(注:只是讨论实参L的前后变化)
虽然这两个函数都是我自己写的,但是事后我仔细想后,又有一些问题困惑了我,所以我先讲一下这两个函数对实参L的作用。
要说这两个函数,先说一下变量的存储。其实呢,在我的理解里面,指针是这样的一个东西:
这个东西这么理解:L:0x2000表示指针L这个变量名存放的地址,而0x6666才是指针变量里面的内容,这个内容存在0x5000这个内存单元中,也就是指针L是指向0x5000这个地址单元的,而这个单元恰好也是个指针,指向地址为0x6666的这个内存地址单元。 也可以这么理解:x=5;这个式子的表示图是这样的:
这个式子中x就像指针L,它们都只是变量名,只是对应地址单元的一个Nickname而已,这个x变量名存在0x6000这个地址单元中,x的值5存在0x8888这个单元。
好了,下面开始讲这两个函数:
首先,抓住理解这两个函数区别的关键:在C语言中,调用某个函数,传递过去的实参的副本,即参数是按值传递的。
第二个函数是经典的 p = p->next 型,意思不用解释了。那么,按照上面对变量存储的解释,将指针L当作实参传递过去的话,传过取得应该是0x6666这个值,在这里,L只是0x6666这个值的一个Nickname。因为L = L->Next 这个语句没有改变L这个链表任何一个 Next 域里面的内容,所以对实参L是不会有任何改变的;
再来看第一个函数。第一个函数就不同了,它通过temp变量多次修改了头结点的Next域的值,也就是对应于上面的变量存储0x6666这个值。比如说把这个值改成了0x5555,是不是就改变了头结点所指向的内存单元了?^_^ 后面的结点就不用说,跟着就连不上了。所以最后头结点指向了实参L的最后一个结点的Next域–NULL。
AC代码:
其中Print()和Read()是我自己写的,不过估计后台写的也差不多#include <stdio.h> #include <stdlib.h> typedef int ElementType; typedef struct Node *PtrToNode; struct Node { ElementType Data; PtrToNode Next; }; typedef PtrToNode List; List Read(); /* 细节在此不表 */ void Print( List L ); /* 细节在此不表;空链表将输出NULL */ List Merge( List L1, List L2 ); int main() { List L1, L2, L; L1 = Read(); L2 = Read(); Print(L1); Print(L2); printf("\n"); L = Merge(L1, L2); Print(L); Print(L1); Print(L2); return 0; } /* Read */ List Read(){ List L = (List)malloc(sizeof(struct Node)); L->Next = NULL; //L为头结点 List tmp = L; ElementType x; while(scanf("%d",&x),x!=-1){ List TempL = (List)malloc(sizeof(struct Node)); TempL->Data = x; TempL->Next = NULL; tmp->Next = TempL; tmp = tmp->Next; } return L; } /* Print */ void Print( List L ){ List Temp = L->Next; if( L->Next == NULL ){ printf("NULL\n"); return; }else{ while( Temp ){ printf("%d ",Temp->Data); Temp = Temp->Next; } printf("\n"); } } /* 你的代码将被嵌在这里 */ List Merge(List L1, List L2){ if( L1->Next == NULL){ List temp,L; L = (List)malloc(sizeof(struct Node)); temp = L2; L2 = L2->Next; L->Next = L2; while( L2 ){ temp->Next = L2->Next; L2 = L2->Next; } return L; }else if( L2->Next == NULL){ List temp,L; L = (List)malloc(sizeof(struct Node)); temp = L1; L1 = L1->Next; L->Next = L1; while( L1 ){ temp->Next = L1->Next; L1 = L1->Next; } return L; } else{ List LL = (List)malloc(sizeof(struct Node)); List LLL = LL; List temp1,temp2; temp1 = L1; temp2 = L2; L1 = L1->Next; L2 = L2->Next; while( L1 && L2){ if(L1->Data < L2->Data){ LL->Next = L1; LL = LL->Next; temp1->Next = L1->Next; L1 = L1->Next; }else{ LL->Next = L2; LL = LL->Next; temp2->Next = L2->Next; L2 = L2->Next; } } while( L1 ){ LL->Next = L1; LL = LL->Next; temp1->Next = L1->Next; L1 = L1->Next; } while(L2){ LL->Next = L2; LL = LL->Next; temp2->Next = L2->Next; L2 = L2->Next; } return LLL; } }
代码比较繁琐,Merge()函数几乎每个if/else都写了很多重复的代码,代码优化的时候提出来就好,我这么写只是为了加深那种把结点“摘下来”的思想。
THE END.
相关文章推荐
- Python对两个有序列表进行合并和排序的例子
- 算法题:合并两个有序列表
- 编程珠玑: 12章 取样问题 12.3设计空间,程序的输入包含两个整数m和n,其中m<n。输出是0~n-1范围内m个随机整数的有序列表,不允许重复。 -------解题总结
- 编程实现两个有序单链表的合并
- 牛客网编程-合并两个有序链表(java)
- Python对两个有序列表进行合并和排序的例子
- Python合并两个有序列表
- 编程珠玑: 12章 取样问题 12.3设计空间,程序的输入包含两个整数m和n,其中m<n。输出是0~n-1范围内m个随机整数的有序列表,不允许重复。 解法2-------解题总结
- [数据结构]第一次作业:将两个有序线形表合并成一个有序表
- 合并两个有序列表的循环和递归实现
- 合并两个有序列表的循环和递归实现
- 算法面试题:找出由两个有序列表合并而成的新列表中的第n个元素
- 已知两个链表 la和 lb,其元素值递增排序。编程将la和lb合并成一个递减有序(相同值元素只保留一个)的链表lc。(北方名校经典试题) 本题选做
- Python合并两个有序列表
- 编程分别输入两个按从小到大排序的数组a和b,将这两个有序数组合并,使合并后的数组仍有序 (从小到大)
- leetcode 第21题 两个有序列表的合并
- 将两个非递减的有序链表合并为一个非递增的有序链表(C语言编程实现)
- 将两个递增的有序链表合并为一个递增的有序链表(C语言编程实现)
- Python--合并两个有序列表
- 将两个表序列表合并为一个有序列表