数据结构课程设计报告 合并果子问题
数据结构课程设计 链表合并

数据结构课程设计链表合并数据结构课程设计 - 链表合并概述:在数据结构课程设计中,链表合并是一个常见的问题。
本文将详细介绍链表合并的概念、算法和实现方法,并提供代码示例和详细解释。
1. 链表的基本概念链表是一种常见的数据结构,用于存储和组织数据。
链表由一系列节点组成,每一个节点包含一个数据元素和一个指向下一个节点的指针。
链表的第一个节点称为头节点,最后一个节点的指针指向空。
2. 链表合并的定义链表合并是指将两个有序链表合并成一个有序链表的操作。
合并后的链表应保持有序性。
3. 链表合并的算法链表合并可以使用迭代或者递归算法来实现。
3.1 迭代算法迭代算法通过比较两个链表的节点值,挨次选择较小的节点插入到新链表中。
具体步骤如下:- 创建一个新链表和一个指向新链表尾部的指针。
- 比较两个链表的节点值,选择较小的节点插入到新链表中,并更新指针。
- 如果其中一个链表为空,将另一个链表的剩余部份直接插入到新链表中。
- 返回新链表的头节点。
3.2 递归算法递归算法通过递归地合并链表的子链表来实现链表合并。
具体步骤如下:- 如果其中一个链表为空,返回另一个链表。
- 比较两个链表的头节点值,选择较小的节点作为合并后的头节点。
- 递归调用合并函数,将较小节点的下一个节点与另一个链表合并,并将结果作为当前节点的下一个节点。
- 返回合并后的头节点。
4. 链表合并的实现方法下面是使用C++语言实现链表合并的示例代码:```cpp#include <iostream>struct ListNode {int val;ListNode* next;ListNode(int x) : val(x), next(NULL) {}};ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {if (l1 == NULL) return l2;if (l2 == NULL) return l1;ListNode* head = NULL;ListNode* tail = NULL;if (l1->val <= l2->val) {head = l1;l1 = l1->next;} else {head = l2;l2 = l2->next;}tail = head;while (l1 != NULL && l2 != NULL) { if (l1->val <= l2->val) {tail->next = l1;l1 = l1->next;} else {tail->next = l2;l2 = l2->next;}tail = tail->next;}if (l1 != NULL) {tail->next = l1;}if (l2 != NULL) {tail->next = l2;}return head;}int main() {// 创建链表1: 1 -> 2 -> 4ListNode* l1 = new ListNode(1);l1->next = new ListNode(2);l1->next->next = new ListNode(4);// 创建链表2: 1 -> 3 -> 4ListNode* l2 = new ListNode(1);l2->next = new ListNode(3);l2->next->next = new ListNode(4);// 合并链表ListNode* mergedList = mergeTwoLists(l1, l2); // 打印合并后的链表ListNode* current = mergedList;while (current != NULL) {std::cout << current->val << " ";current = current->next;}return 0;}```以上代码使用迭代算法实现了两个有序链表的合并。
数据结构 求集合并集交集实验报告

实验报告题目:集合的并、交和差运算班级:13信息管理姓名:刘学号:20130403012 完成日期:20,11一、需求分析1[问题描述]编制一个能演示执行集合的并、交和差运算的程序。
2[基本要求](1)集合的元素限定为整数。
(2)用链式存储结构完成。
3.测试数据set1={ 1 2 3 4 5 },set2={ 3 4 5 6 7 }set1∪set2={ 1 2 3 4 5 6 7 };set1∩set2={ 3 4 5 }set1-set2={ 1 2 }二、编码实现1.存储类型typedef struct LNode{int data;struct LNode *next;}LNode,*LinkList;2.部分函数的伪码算法//构造一个集合void CreateList_L(LinkList &L){LinkList p;int n,i;printf("请输入元素个数:\n");scanf("%d",&n);L=(LinkList)malloc(sizeof(LNode));L->next=NULL;printf("请一次输入各个元素:\n");for(i=n;i>0;--i){p=(LinkList)malloc(sizeof(LNode));scanf("%d",&p->data);p->next=L->next;L->next=p;}}//取出数据值int get_data(LinkList h){int t;t=h->data;return t;}//删除与t相同的节点LinkList del(LinkList L1,int t){LinkList p1,p2;p1=L1->next;while(t!=p1->data&&p1->next!=NULL){p2=p1,p1=p1->next;}if(t==p1->data){if(p1==L1->next)L1->next=p1->next;elsep2->next=p1->next;}return L1;}//打印集合void printf_L(LinkList &L){LinkList h;h=L->next;while(h){printf(" %d ",h->data);h=h->next;}}//集合排序void sort(LinkList &L){LinkList p=L->next,q,r;if(p){r=p->next;p->next=NULL;p=r;}while(p){r=p->next;q=L;while(q->next!=NULL&&q->next->data<p->data) q=q->next;p->next=q->next;q->next=p;p=r;}}//集合并集void combine(LinkList &L1,LinkList L2){LinkList p,h;p=L1;while(p->next){p=p->next;}p->next=L2->next;sort(L1);p=L1->next;while(p->next){if(p->data==p->next->data){h=p->next;p->next=h->next;free(h);}elsep=p->next;}}//集合的差void differ(LinkList L1,LinkList L2){int t;LinkList h;h=L2->next;while(h){t=get_data(h);L1=del(L1,t);h=h->next;}}//交集void intersectLink(LinkList L1,LinkList L2) {LinkList p,h;p=L1;while(p->next){p=p->next;}p->next=L2->next;sort(L1);p=L1;while(p->next->next){h=p->next->next;if(p->next->data!=h->data){p->next=h;h=h->next;}elsep=p->next;}p->next=NULL;}三、调试分析1,说实话,自己根本不会做,参考网上的资料都做不出来;2,自己做的程序,没有任何错误,但就是不能运行;3,对链表的认识不够深入,不知道如何构造链表,以及实现各种操作;四、测试结果set1={ 1 2 3 4 5 },set2={ 3 4 5 6 7 }set1∪set2={ 1 2 3 4 5 6 7 };set1∩set2={ 3 4 5 }set1-set2={ 1 2 }五.附录#include<stdlib.h>typedef struct LNode{int data;struct LNode *next;}LNode,*LinkList;//构建集合函数void CreateList_L(LinkList &L){LinkList p;int n,;i;printf("请输入元素个数:\n");scanf("%d",&n);L=(LinkList)malloc(sizeof(LNode));L->next=NULL;printf("请一次输入各个元素:\n");for(i=n;i>0;--i){p=(LinkList)malloc(sizeof(LNode));scanf("%d",&p->data);p->next=L->next;L->next=p;}}//获取数据函数int get_data(LinkList h){int t;t=h->data;return t;}//删除函数LinkList del(LinkList L1,int t){LinkList p1,p2;p1=L1->next;while(t!=p1->data&&p1->next!=NULL){p2=p1,p1=p1->next;}if(t==p1->data){if(p1==L1->next)L1->next=p1->next;elsep2->next=p1->next;}return L1;}//打印函数void printf_L(LinkList &L){LinkList h;h=L->next;while(h){printf(" %d ",h->data);h=h->next;}}//排序void sort(LinkList &L){LinkList p=L->next,q,r;if(p){r=p->next;p->next=NULL;p=r;}while(p){r=p->next;q=L;while(q->next!=NULL&&q->next->data<p->data) q=q->next;p->next=q->next;q->next=p;p=r;}}//并集void combine(LinkList &L1,LinkList L2)LinkList p,h;p=L1;while(p->next){p=p->next;}p->next=L2->next;sort(L1);p=L1->next;while(p->next){if(p->data==p->next->data){h=p->next;p->next=h->next;free(h);}elsep=p->next;}}//求差void differ(LinkList L1,LinkList L2) {int t;LinkList h;h=L2->next;while(h){t=get_data(h);L1=del(L1,t);h=h->next;}}//交集void intersect(LinkList L1,LinkList L2) {LinkList p,h;p=L1;while(p->next){p=p->next;}p->next=L2->next;sort(L1);p=L1;while(p->next->next){h=p->next->next;if(p->next->data!=h->data){p->next=h;h=h->next;}elsep=p->next;}p->next=NULL;}//主函数int main(){LinkList L1,L2;int t;printf("求集合交集请按1\n求集合并集请按2\n请集合之差请按3\n");scanf("%d",&t);while(t!=0){switch(t){case 1:CreateList_L(L1);CreateList_L(L2);intersect(L1,L2);sort(L1);printf_L(L1);break;case 2:CreateList_L(L1);CreateList_L(L2);combine(L1,L2);sort(L1);printf_L(L1);break;case 3:CreateList_L(L1);CreateList_L(L2);differ(L1,L2);sort(L1);printf_L(L1);break;default :printf("error\n");}scanf("%d",&t);}return 0;}11。
合并两个链表课程设计

合并两个链表课程设计一、课程目标知识目标:1. 学生能理解链表的概念,掌握链表的基本操作,如插入、删除节点。
2. 学生能理解合并两个链表的过程,掌握合并算法的实现。
3. 学生能理解递归思想,并运用递归方法解决合并链表问题。
技能目标:1. 学生能运用所学知识,独立编写合并两个链表的程序。
2. 学生能够通过调试程序,找出并修正链表操作中的错误。
3. 学生能运用所学算法,解决实际问题,提高编程能力。
情感态度价值观目标:1. 学生培养对数据结构与算法的兴趣,认识到编程解决问题的价值。
2. 学生培养合作精神,学会在团队中分享、讨论和解决问题。
3. 学生培养良好的编程习惯,注重代码规范,提高代码质量。
分析课程性质、学生特点和教学要求:本课程为计算机科学或信息技术相关课程的章节,适用于高年级学生。
学生在学习本章节前,已具备基本的编程能力和数据结构知识。
课程旨在巩固学生的链表知识,提高编程技能,培养解决实际问题的能力。
课程目标具体、可衡量,旨在使学生能够独立完成合并两个链表的任务,并通过教学设计和评估,确保学生达到预期学习成果。
二、教学内容1. 链表基础知识回顾:包括链表的定义、节点结构、链表的分类(单向链表、双向链表等)。
2. 链表基本操作:插入、删除节点的方法及实现,重点讲解递归在链表操作中的应用。
3. 合并两个链表的概念:介绍合并链表的意义,分析合并过程中需注意的问题。
4. 合并算法讲解:详细讲解两种合并链表的方法(非递归和递归方法),并分析其优缺点。
5. 编程实践:指导学生编写合并两个链表的程序,要求学生独立完成,并注重代码规范。
6. 调试与优化:教授学生如何调试链表程序,找出并修正错误,提高程序性能。
教学内容安排和进度:1. 第一课时:回顾链表基础知识,讲解链表基本操作。
2. 第二课时:介绍合并两个链表的概念,讲解合并算法。
3. 第三课时:指导学生进行编程实践,完成合并链表的程序。
4. 第四课时:学生展示编程成果,讨论和解决编程过程中遇到的问题,进行调试与优化。
数据结构实验报告 有序表的合并(优质参考)

数据结构实验报告实验题目:有序表的合并姓名:张耀班级:计嵌151学号: 1513052017一、实验目的把两个有序表归并为一个有序表。
二、数据结构设计(1)存储设计:采用带头结点的单链表存储数据。
输入:数据通过键盘有序输入输出:屏幕显示两个有序表及归并后的表(2)函数设计:CreateList(int n);// 创建具有n个元素的线性链表ListDisplay();//输出表元素Combine(LinkList LA, LinkList LB);//归并单链表LA,LB(3)两个有序表合并算法描述:Step1:初始化。
1.1设置工作指针pa,pb,分别指向两个有序表LA,LB的首元结点。
1.2生成新表LC的头结点,工作指针pc指向LC。
Step2:只要pa和pb有所指,循环执行下列操作。
2.1生成一新节点,链到LC表尾,pc指向它。
2.2如果pa->data<=pb->data:pc->data=pa->data;pa后移。
2.3否则:pc->data=pb->data;pb后移。
Step3:如果pa空,把pb开始的结点依次复制到pc后。
Step4: 如果pb空,把pa开始的结点依次复制到pc后。
三、算法设计与N-S图(1)算法设计:求归并表的过程是在元素有序的情况下不断地从两表中取出元素,添加到新表中,所以元素采取表尾插入。
设两个有序表SA,SB,归并后的有序表为SC,取元素的过程是:依次扫描SA,SB中的元素,比较当前元素的值,将较小的元素赋给SC,直到一个顺序有序表扫描完毕,然后将另一个顺序有序表中余下元素复制到SC中。
(2)程序流程图开始初始化:pa = LA.Head->next; pb = LB.Head->next;pc = Head;pa和pb都不为空生成新节点,连接到LC表尾,pc指向它pa->data<=pb->datapc->data = pb->data;pb = pb->next;pc->data = pa->data;pa = pa->next;pa==N ULLPb!=NULL把pb开始的结点依次复制到pc后面pb==N ULLPa!=NULL把pa开始的结点依次复制到pc后面四、程序清单#include<iostream>using namespace std;结束#include"process.h"struct Node{int data;//数据域,存放表元素Node *next;//指针域,指向下一个结点};class LinkList{private:Node *Head;// 链表头指针public:LinkList();//构造函数,创建空链表void CreateList(int n);//创建具有n个元素的线性链表void ListDisplay();//输出表元素void Combine(LinkList, LinkList);//合并};LinkList::LinkList(){//构建函数,建一空链表Head = new Node;Head->next = NULL;}void LinkList::CreateList(int n){//尾插法(正序)创建具有n个元素的线性表Node *p, *s;//设置工作指针。
语言数据结构实验报告链表的合并-7页word资料

《数据结构》实验报告◎实验题目:合并两个链表:设A与B分别为两个带有头结点的有序循环链表(所谓有序是指链接点按数据域值大小链接,本题不妨设按数据域值从小到大排列),list1和list2分别为指向两个链表的头指针。
请写出将这两个链表合并为一个带头结点的有序循环链表的算法。
◎实验目的:使用顺序表的创建、插入、删除、合并等操作编写关于数据结构的程序。
◎实验内容:写出程序并上机调试、通过。
一、需求分析1、演示程序以用户和计算机的对话方式执行,即在计算机终端上显示“Please input the first list”时输入第一个链表的元素个数和元素。
当出现“Please input the second list”时输入第二个链表的元素个数和元素。
然后计算机终端输出合并后的链表。
2、输出的形式为两个链表中的元素合并成一个链表并且其中元素按照递增的顺序排列。
3、程序执行的命令包括:(1)构造含n个元素的循环链表;(2)输入数据;(3)将输入的数据作成循环链表;(4)合并;(5)输出;(6)结束。
4、本程序能将两个链表合并成一个链表。
并且合并后的链表中的元素是原来两个链表中的元素按照递增顺序的排列。
5、输入及输出示例:例1:Please input the first list41 3 7 9Please input the second list51 2 5 6 8Output the mergelist1 2 3 5 6 7 8 9Press any key to continue例2:Please input the first list51 2 5 9 11Please input the second list31 2 8Output the mergelist1 2 5 8 9 11Press any key to continue二概要设计1.基本操作本程序中,用单向有序循环链表作为存储结构。
数据结构课程设计实现两个链表的合并讲课讲稿

数据结构课程设计实现两个链表的合并一、需求分析:题目:实现两个链表的合并问题描述:1. 建立两个链表A和B,链表元素个数分别为m和n个。
2. 假设元素分别为(x1,x2,…xm),和(y1,y2, …yn)。
把它们合并成一个线形表C,使得:当m>=n时,C=x1,y1,x2,y2,...xn,yn, (x)当n>m时,C=y1,x1,y2,x2,…ym,xm,…,yn输出线性表C。
由题目的相关信息可以分析得到:首先我们需要建立两个链表AB,A链表的元素个数为m;B链表的元素个数为n;在将A\B链表进行合并,更具m和n的大小关系决定链表C的元素顺序;再将C经行直接插入排序得到一个新的链表D;最后输出ABCD的相关信息。
二、算法的流程图三、算法设计分析这个两个链表的交叉合并算法主要运用到的是链表的基本操作,定义节点,将链表的创建、计算链表的长度、链表A,B的交叉组合、链表内容升序排列、删除链表指定位置元素、删除指定的元素等算法写成了独立函数,通过主函数调用。
这样就大大精简了主函数的操作。
但主函数中很大篇幅用到了if、else语句,用以指定链表指定结点和指定元素的删除操作,这样就使得本来很精简变得繁琐,降低了程序的质量。
所以其有优点和缺点,但需要不断的改进,不断优化该程序。
四、源代码程序源代码:#include<stdio.h>#include<stdlib.h>typedef struct node //节点定义{int data;struct node *next;} node,*linklist;linklist creat(linklist head) //该函数用来创建链表{node *r,*s;int a;r = (linklist)malloc(sizeof(node));head = r;scanf("%d",&a);while(a != 0){s =(node*)malloc(sizeof(node));s->data=a;r->next=s;r=s;printf("please input a data:");scanf("%d",&a);}r->next=NULL;return head;}linklist length(linklist l) // 返回L中数据元素个数{int i=0;linklist p=l->next; // p指向第一个结点while(p){i++;p=p->next;}return i;}linklist mergel(linklist A,linklist B) //用于实现链表A,B的交叉组合 {int m,n;node *p,*q,*s,*t;linklist C;p=A->next;q=B->next;m=length(A);n=length(B);C=A;if(m<n){p=B->next;q=A->next;C=B;}while(p&&q){s=p->next;p->next=q;if(s){t=q->next;q->next=s;}p=s;q=t;}return C;}linklist sort(linklist L) //链表内容升序排列{linklist p,q,min;int temp;p=L;while( p=p->next ){q=min=p;while(q=q->next){if( q->data<min->data )min = q;}if( min!=p ){temp = p->data;p->data = min->data;min->data=temp;}}return L;}linklist Delete(linklist l,int index) //删除链表指定位置元素{ linklist p,t;int cx=1; //用于计数p=l;if(index<length(l)){while(p&&(cx<index)){t=p;p=p->next;cx++;}t->next=p->next;}elseprintf("input indext error");return l;}linklist Delete_element(linklist l,int data) //删除指定的元素{ linklist p;p=l;if(p->next){while(p->next->data!=data){p=p->next;}p->next=p->next->next;}elseprintf("don't faind the element");return l;}linklist display(linklist l) //打印{ linklist p;printf("new linklist :\n");p = l->next;while(p){printf("%d\n",p->data);p= p->next;}return l;}main(){linklist p,q,A,B,C,D;int indexs;int datas;char name;int cmd;printf("Creat linklist A:\n"); //创建A链表,并打印printf("please input a data:");A = creat(A);printf("Creat linklist B:\n"); //创建B链表,并打印printf("please input a data:");B = creat(B);C = mergel(A,B); //生成C链表,并打印 printf("linklist C\n");p = C->next;while(p){printf("%d\n",p->data);p=p->next;}D=C; //对C进行排序生成D sort(D);printf("linklist D:\n");q = D->next;while(q){printf("%d\n",q->data);q = q->next;}printf("\nplease input 0 or 1 \n");//用1和0判断是按位置删除还是直接删除元素scanf("%d",&cmd);if(cmd==0) //位置删除{printf("please input linklist name\n ");fflush(stdin);scanf("%c",&name);printf("\nplease input index \n");scanf("%d",&indexs);fflush(stdin);if(name=='A'){Delete(A,indexs);display(A);}else if(name=='B'){Delete(B,indexs);display(B);}else if(name=='C'){Delete(C,indexs);display(C);}else if(name=='D'){Delete(D,indexs);display(D);}elseprintf("nameError");}else if(cmd==1) //元素删除{fflush(stdin); //清除缓冲printf("please input linklist name\n ");//fflush(stdin);scanf("%c",&name);printf("\nplease input datas \n");scanf("%d",&datas);if(name=='A'){Delete_element(A,datas);display(A);}else if(name=='B'){Delete_element(B,datas);display(B);}else if(name=='C'){Delete_element(C,datas);display(C);}else if(name=='D'){Delete_element(D,datas);display(D);}elseprintf("name2error");}elseprintf("cmdError");printf("\nOver\n");getchar();return 0;}六、实验运行结果显示:设计体会及今后改进的意见;短短一周的数据结构课程设计结束了,回想着这一周自己的表现,感觉不是很满意,感到自己许多不足之处。
(完整word版)数据结构课程设计_集合的并、交和差运算(word文档良心出品)

一、课程题目会合的并、交和差运算二、问题描绘功能:编制一个能演示履行会合的并、交和差运算的程序。
三、基本要求1)会合的元素限制为小写字母字符【‘ a’ ..‘ z’】2)演示程序以用户和计算机的对话方式履行。
四、测试数据(1) Set1= ”magazine ” , Set2= ’ paper ” ,Set1∪Set2= ”aegimnprz ” ,Set1∩Set2= ”ae” ,Set1-Set2=”gimnz”;(2) Set1= ” 012oper4a6tion89 ”,Set2= ”error data ” , Set1 ∪Set2= ” adeinoprt ” ,Set1 ∩Set2= ” aeort ” , Set1-Set2= ” inp ” .五、算法思想为了实现上述程序的功能,应以有序链表表示会合。
为此,需要两个抽象数据种类:有序表和会合。
1、有序表的抽象数据种类定义为:input(linklist l)初始条件: l 是以 l 为头节点的空链表。
操作结果:生成以l 为头节点的非空链表。
output(linklist l)初始条件: l 是以 l 为头节点的非空链表。
操作结果:将以l 为头节点的链表中数据逐一输出。
2、会合的抽象数据种类定义为:heji(linklist A,linklist B,linklist C)初始条件:链表A、B、C 已存在操作结果:生成一个由 A 和 B 的并集组成的会合C。
jiaoji(linklist A,linklist B ,linklist ,C)初始条件:链表A、B、C 已存在操作结果:生成一个由 A 和 B 的交集组成的会合C。
六、模块化分本程序抱含四个模块:1)节点构造单元模块——定义有序表的节点构造;2)有序表单元模块——实现有序表的抽象数据种类;3)会合单元模块——实现会合获取抽象数据种类;4)主程序模块:Void main () {初始化;do{接授命令;办理命令;}while (“命令” != “退出”);}七、源程序#include<stdio.h>#include<string.h>#include<stdlib.h>#include<conio.h>typedef struct node{int data;struct node* next;}lnode,*linklist;lnode *init_lnode();void input(linklist l);void jiaoji(linklist A,linklist B,linklist C); void heji(linklist A,linklist B,linklist C); void output(linklist l);void main(){lnode *a,*b,*c;a=init_lnode();b=init_lnode();c=init_lnode();printf(" 求 AB 会合的交集和并集\n");printf(" 请输入 A 会合的元素 :");input(a);printf("\n 请输入 B 会合的元素 :");input(b);printf("\n 输入达成 \n");printf("\n 按随意键进入主菜单:");getch();do{char menu[]={"\n\n\n-----☆ 1.交集运算☆---------\n\n""--------- ☆ 2 和集运算☆ ---------\n\n""--------- ☆3.差集运算☆---------\n\n""--------- ☆ 0.退出☆ ---------\n\n" };printf("%s",menu);printf("\n 请在 0-3 中选择 :");scanf("%d",&sel);switch(sel){case 1:printf("AB会合的交集是:");jiaoji(A,B,C);output(C);C->next=NULL;break;case 2:printf("AB的合集是:");heji(A,B,C);output(C);C->next=NULL;break;case 3:chaji(A,B,C);break;case 0:break;}}while(sel!=0);}/* 主函数结束 */ /**********初始化函数 ***************/lnode * init_lnode(){lnode *l;l=(lnode *)malloc(sizeof(lnode));l->next=NULL;return l;}/***************录入函数 ********************/ void input(linklist l){lnode *s;int x;scanf("%d",&x);while(x!=0){s=(lnode *)malloc(sizeof(lnode));s->data=x;s->next=l->next;l->next=s;scanf("%d",&x);}}/************交集函数 *********************/ void jiaoji(linklist A,linklist B,linklist C){lnode *p,*q,*t;p=A->next;while(p!=NULL){q=B->next;while((q!=NULL)&&(q->data!=p->data))q=q->next;if((q!=NULL)&&(q->data==p->data)){t=(lnode*)malloc(sizeof(lnode));t->data=p->data;t->next=C->next;C->next=t;}p=p->next;}}/***********输出函数 *****************/void output(linklist l){lnode *s;s=l->next;while(s!=NULL){printf("%5d",s->data);s=s->next;}printf("\n");}/******** 并集函数 *************************/ void heji(linklist A,linklist B,linklist C){lnode *p,*q,*t;p=A->next;while(p!=NULL){t=(lnode*)malloc(sizeof(lnode));t->data=p->data;t->next=C->next;C->next=t;p=p->next;}q=B->next;while(q!=NULL){p=A->next;while((p!=NULL)&&(p->data!=q->data))p=p->next;if (p==NULL){t=(lnode*)malloc(sizeof (lnode));t->data=q->data;t->next=C->next;C->next=t;}q=q->next;}/*********************差集函数 ****************/ void chaji(linklist A,linklist B, linklist C){lnode *p,*q,*s,*t;p=A->next;printf("A与B的差集是:\n");while(p!=NULL){q=B->next;while((q!=NULL)&&(p->data!=q->data))q=q->next;if(q==NULL){s=(lnode*)malloc(sizeof(lnode));s->data=p->data;s->next=C->next;C->next=s;}p=p->next;}output(C);C->next=NULL;q=B->next;printf("B 与 A 的差集是 :\n");while(q!=NULL){p=A->next;while((p!=NULL)&&(p->data!=q->data)) p=p->next;if(p==NULL){t=(lnode*)malloc(sizeof(lnode));t->data=q->data;t->next=C->next;C->next=t;}q=q->next;}output(C);}} 四、测试数据及程序运转状况程序运转结果 :八、心得领会1、因为对会合的三种运算的算法斟酌不足,在链表种类及其尾指针的设置时出现错误,以致程序低效。
两线性表的合并 数据结构实验报告

3.程序采用逐个输入的方法创建 La,Lb,在元素较多时,会使得程序很庞大,不利于检查错
误等。
4. 算法的时空分析
各操作的算法时间复杂度比较合理 initlist 为 O(1)printList,delsame,change,creatlist 为 O(l.length), addList 为 O(la.length*lb.length)。
六、测试结果
在 TC2.0 中运行得到的结果如下图所示:
5
七、附录:源程序 #include<stdio.h> #include<malloc.h>
#define listinitsize 100 #define OVERFLOW -1
/*线性表的定义*/ typedef struct sqlist {
} while(i<=la.length)
{ lc.a[k]=la.a[i]; k++; i++; } while(j<=lb.length) { lc.a[k]=lb.a[j]; k++; j++;
7
} lc.length=k-1; return lc; } /*打印线性表*/ void printlist(sqlist l) { int i=1; for(i=1;i<=l.length;i++)
printf("%6d",l.a[i]); printf("\n"); } /*删除线性表中的相同的元素*/ sqlist delsame(sqlist L) { int i,j,k; if(L.length>0) {
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
合肥学院
计算机科学与技术系
课程设计报告
2011 ~2012 学年第二学期
课程数据结构与算法
课程设计名称合并果子问题
学生姓名杜双双
学号1004013037
专业班级计算机科学与技术10级3班
指导教师李红陈艳平王竹婷
2012 年2 月
课程设计报告
一、问题分析和任务定义
此程序需要完成如下要求:在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。
多多决定把所有的果子合成一堆。
每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。
可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了。
多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。
因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。
假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。
例如有3种果子,数目依次为1,2,9。
可以先将1、2堆合并,新堆数目为3,耗费体力为3。
接着,将新堆与原先的第三堆合并,又得到新的堆,数目为12,耗费体力为12。
所以多多总共耗费体力3+12=15。
可以证明15为最小的体力耗费值。
实现本程序需要解决以下几个问题:
1、要使每次合并的体力消耗最小应该选择数目最小的两堆果子,那么如何选择出两堆最小的呢?
2、选择出了两堆果子如何进行合并?
3、如何计算最小的体力耗费值?
本问题的关键和难点在于数据结构的选择,找出最优的方法,在此选择哈夫曼树数据结构。
示例:三种果子,果子数目分别为1,2,3
哈夫曼树
最小体力消耗值:3+6=9
二、数据结构的选择和概要设计
上面采用哈夫曼树,则其存储就是哈夫曼树的存储结构。
采用数组顺序存储结点信息。
每一个结点包括四个域:存放该结点的weight 域、分别存放其左右孩子结点在数组中下标的lchild 域和rchild 域,以及记录该结点的父结点信息的parent 域。
只需用一个主函数就能解决问题。
三、详细设计和编码
数据结构:
typedef struct {
int weight;
int parent,lchild,rchild;
}hufmtree;
若给定n种果子的数目,则可定义数组tree[]存储哈夫曼树上的结点:
详细设计算法如下:
(1)初始化数组tree[];读入给定的n种果子每种果子数,分别放入数组的前n个分量的weight域中,并将数组中所有分量的lchild域、rchild域和parent域置0.
for(i=0;i<n;i++)//初始化数组
{
tree[i].parent=0;
tree[i].lchild=0;
tree[i].rchild=0;
tree[i].weight=0;
}
(2)从数组的前n个分量中选择果子数目最小和次小的两个结点(假设下标分别为p1和p2)合并,产生新结点,将新结点的信息存放在第n+1个分量中;新结点的数目为两个结点数目值之和,左右孩子域中的值分别修改为p1和p2;同时,改变下标为p1和p2结点的parent域中的值,使其等于n+1。
for(i=n;i<m;i++)//进行合并
{
p1=p2=0;
s1=s2=ma;
for(j=0;j<=i-1;j++)//选出两个果子数目最小的根结点
{
if(tree[j].parent==0)
if(tree[j].weight<s1)//查找最小
{s2=s1;
s1=tree[j].weight;
p2=p1;
p1=j;
}
else if(tree[j].weight<s2)//查找次小
{
s2=tree[j].weight;
p2=j;
}
tree[p1].parent=tree[p2].parent=i;
tree[i].weight=tree[p1].weight+tree[p2].weight;
tree[i].lchild=p1;
tree[i].rchild=p2;
}
}
(3)重复(2),每次均从parent域的值为0的所有结点中选择数目最小和次小的两个结点合并,产生的新结点顺次存放在weight域值为0的分量中,同时修改该分量的左右孩子域值和
被合并的两个结点的parent域值,知道数组的第2n-1个分量的weight域、lchild域和rchild 域中的值被修改为止。
(4)将每次合并后产生的新结点的weight域中的值进行求和
sum=sum+tree[i].weight;
四、上机调试过程
1、语法错误及修改:由于本程序只使用了哈夫曼树的构造,所以程序可以相对来说得到简化,语句很少。
出现的问题主要是变量的定义,括号的配对。
这些问题均根据编译器的警告提示,对应将其解决。
2、逻辑问题修改和调整:本程序虽然只用到了哈夫曼树的构造,但在构造哈夫曼树的过程中也有不少是值得关注的。
寻找最小和次小结点,将它们合并,也是说易不易的。
其中主要运用了for循环语句,根据指定条件的判断,找结点,合并结点,并将产生的新结点求和。
3、时间,空间性能分析:本算法的空间复杂度很低,只需要一个一维数组存放结果即可。
因此空间复杂度为O(n)。
选取两个最小值需要逐个比较,所以时间复杂度为O(n^2)。
4、经验和体会:初拿到本课题,开始想到的是堆栈,后分析觉得用哈夫曼树,在考虑问题时要全面,不要总在字面意思上看,思考建立模型,解决问题的能力得以提高。
五、测试结果及其分析
在运行环境中运行程序显示:
根据显示说明按要求输入数据:3
键盘输入3,按enter,显示如下:
根据要求输入三个数字:
程序根据输入的数据计算出最小体力耗费值
重新运行输入其他数据情况:
输入不正确情况:将数据输入改为字符输入程序运行后如下
六、用户使用说明
程序名为果子合并问题.c,运行环境为vc++。
程序执行后显示
输入果子的种类(1到10000之间):
在键盘按要求输入数字之后如3,按enter键显示:
输入果子的种类(1到10000之间):3
依次输入每种果子的数目(1到20000之间):
在键盘按要求输入数字(如1,2,3),按enter键显示结果:
依次输入每种果子的数目(1到20000之间):1 2 9
最小体力消耗值:15
七、参考文献
[1] 王昆仑,李红.数据结构与算法. 北京:中国铁道出版社,2006年5月。
八、附录
#include "stdio.h"
#define max 10000
#define ma 20000
typedef struct
{
int weight;
int parent,lchild,rchild;
}hufmtree;
hufmtree tree[2*max-1];
main()
{
int i,m,f,n,j;
int sum=0,p1,p2,s1,s2;
printf("输入果子的种类:");
scanf("%d",&n);
m=2*n-1;
for(i=0;i<n;i++)//初始化数组
{
tree[i].parent=0;
tree[i].lchild=0;
tree[i].rchild=0;
tree[i].weight=0;
}
printf("依次输入每种果子的数目:");
for(i=0;i<n;i++)//读入果子的数目
{
scanf("%d",&f);
tree[i].weight=f;//依次赋值每种果子的数目
}
for(i=n;i<m;i++)//进行合并
{
p1=p2=0;
s1=s2=ma;
for(j=0;j<=i-1;j++)//选出两个果子数目最小的根结点 {
if(tree[j].parent==0)
if(tree[j].weight<s1)//查找最小
{s2=s1;
s1=tree[j].weight;
p2=p1;
p1=j;
}
else if(tree[j].weight<s2)//查找次小
{
s2=tree[j].weight;
p2=j;
}
tree[p1].parent=tree[p2].parent=i;
tree[i].weight=tree[p1].weight+tree[p2].weight; tree[i].lchild=p1;
tree[i].rchild=p2;
}
sum=sum+tree[i].weight;
}
printf("最小体力耗费值:");
printf("%d\n",sum);
}。