文本编辑《数据结构》上机实验报告
数据结构上机报告3个

《数据结构》实验报告一题目:快速排序班级:学号:姓名:日期:程序名:一、上机实验的问题和要求:一趟快速排序示例,关键字序列:{52, 49, 80, 36, 14, 58, 61, 97, 23, 75}二、程序设计的基本思想,原理和算法描述:基本思想快速排序是通过比较关键字,以某个记录为界(称为支点记录),将待排序列分成两个部分。
其中一部分所有记录的关键字大于或等于支点记录的关键字,另一部分所有关键字小于支点记录的关键字。
将待排序列按关键字以支点记录分成两部分的过程,称为一次划分,或一趟快速排序三、源程序及注释:int partition(Record r[ ], int low, int high){int k;r[0]=r[low];k=r[low].key;while(low<high){while(low<high&&r[high].key>=k)high--;r[low]=r[high];while(low<high&&r[low].key<k)low++;r[high]=r[low];}r[low]=r[0];return low;}void main(){Record r[size];int i=1, j, k, low=1, high;printf("输入关键字序列:\n");scanf("%d", &k);while(k!=0){r[i++].key=k;scanf("%d", &k);}high=i-1;partition(r, low, high);printf("一趟快速排序之后的关键字序列为:\n");for(i=1;i<=high;i++)printf("%d ", r[i].key);printf("\n");}四、运行输出结果:五、调试和运行程序过程中产生的问题及采取的措施:六、对算法的程序的讨论、分析,改进设想,其它经验教训:七、对实验方式、组织、设备、题目的意见和建议:。
《数据结构》实验报告

《数据结构》实验报告目录一、实验概述 (2)二、实验原理 (2)2.1 数据结构基本概念 (3)2.2 选择的数据结构类型 (4)2.3 实验原理说明 (5)三、实验步骤 (6)3.1 实验准备 (7)3.2 数据结构选择与实现 (7)3.2.1 数据结构类型选择 (9)3.2.2 数据结构实现细节 (9)3.3 实验功能实现 (10)3.3.1 功能一 (11)3.3.2 功能二 (12)四、实验结果与分析 (13)4.1 实验数据 (15)4.2 结果展示 (16)4.2.1 结果一展示 (17)4.2.2 结果二展示 (17)4.3 结果分析 (18)4.3.1 结果一分析 (19)4.3.2 结果二分析 (20)五、实验总结与讨论 (22)5.1 实验总结 (23)5.2 实验中遇到的问题及解决方法 (24)5.3 对数据结构的认识与体会 (25)5.4 对实验教学的建议 (27)一、实验概述本次实验旨在通过实际操作,加深对《数据结构》课程中所学理论知识的理解和掌握。
实验内容围绕数据结构的基本概念、常用算法以及在实际应用中的实现进行设计。
通过本次实验,学生将能够:理解并掌握线性表、栈、队列、链表、树、图等基本数据结构的特点和适用场景。
掌握常用的数据结构操作算法,如插入、删除、查找等,并能够运用这些算法解决实际问题。
学习使用C++、或其他编程语言实现数据结构的操作,提高编程能力和算法设计能力。
本次实验报告将对实验的目的、内容、步骤、结果及分析等方面进行详细阐述,旨在通过实验过程的学习,提高学生对数据结构理论知识的理解和应用能力。
二、实验原理数据结构的基本概念:介绍数据结构的基本定义,包括数据元素、数据集合、数据关系等基本概念,以及数据结构的三要素:逻辑结构、存储结构和运算。
栈和队列:介绍栈和队列的定义、特点、基本运算及其在算法设计中的重要性。
树和二叉树:讲解树的基本概念、二叉树的结构特点、遍历方法、二叉搜索树及其在数据检索中的应用。
文本编辑《数据结构》上机实验报告

成都信息工程学院计算机系课程实验报告一【上机实验目的】要求功能与界面模拟WINDOWS记事本,支持鼠标,因为记事本功能较多,可以根据自己的能力模拟出部分功能,文本编辑这部分功能必须实现,主要利用串的知识。
二【实验环境】PC机每人1台三【上机实验内容】要求功能与界面模拟WINDOWS记事本,支持鼠标,因为记事本功能较多,可以根据自己的能力模拟出部分功能,文本编辑这部分功能必须实现,主要利用串的知识。
四【上机调试程序流程图】(注:可打印)在此程序中,主要包含了添加、插入、删除、复制、剪切、粘贴、还有文件操作。
五【上机调试中出现的错误信息、错误原因及解决办法】1、开始的时候当我输入字符的时候,总是输不进去,经过检查才知道,我忘了把字符输出到屏幕上。
2、在删除的时候,当一行删除完的时候,光标并不会上移到上一行。
然后我通过判断当这光标处的坐标减一后为零(表示这行没有字符了)的时候,然后重新读取光标,让光标显示在上一行。
3、在进行插入操作之后,移动光标会出现问题,就好像插入的字符并没有在链表当中一样。
然后我写了一个测试函数,来判断插入后链表是否满足每列的字符数不得超过80个字符。
然后让每列的字符数都在链表当中,满足要求。
六【上机调试后的源程序及还存在的问题】(注:源程序可打印)/*文本编辑器editor源代码*/#include <stdio.h>#include <conio.h>#include <bios.h>#include <math.h>#define LEFT 0x4b00 /*←:光标左移*/#define RIGHT 0x4d00 /*→:光标右移*/#define DOWN 0x5000 /*↓键:光标下移*/#define UP 0x4800 /*↑键:光标上移*/#define ESC 0x011b /*ESC键:取消菜单打开操作*/#define ENTER 0x1c0d /*回车键:换行*/#define BACK 3592 /*BackSpace键:删除当前光标位置前一个字符*/#define CL 29440 /*ctrl+←键:从右至左,选定文本*/#define CR 29696 /*ctrl+→键:从左到右,选定文本*/#define Cc 11779 /*ctrl+c键:将选定文本,复制一份到剪贴板中*/#define Cv 12054 /*ctrl+v键:将剪贴板中的内容复制到当前位置*/#define Cx 11544 /*ctrl+x键:对选定文本,执行剪切操作*/#define F1 15104 /*F1键:打开文件菜单*/#define F2 15360 /*F2键:打开编辑菜单*/#define F3 15616 /*F3键:打开帮助菜单*/int value,backup;/*value保存有值数组元素的最大下标值,backup保存value的副本,NUM保存当前行中的用户输入的字符个数*/typedef struct record{char ch; /*保存一字符*/int col, line; /*x轴和y轴坐标*/}record;record r[500]; /*定义一个有500个元素的结构体数组,保存选定的文本字符的属性*/typedef struct node /*定义保存行中的单个字符的结构*/{char ch; /*数据域:保存一字符*/struct node *next; /*指针域:指向下一个结点的指针*/}node;/*由此类型节点构成的单链表,命名为:列单链表*/typedef struct Hnode /*定义保存所有列单链表首节点的指针的结构*/{node *next; /*指向列单链表的首节点的地址*/struct Hnode *nextl; /*指向下一个节点的指针*/}Hnode;/*由此类型节点构成的单链表,命名为:行单链表*/void view(Hnode *q) /*按行显示保存在单链表中的文本字符,q为指向行单链表中第一个节点的指针*/{node *p; /*p为保存列单链表节点元素地址的指针*/clrscr(); /*清屏*//*双重循环,读取并显示保存在单链表中字符*/do{p=q->next;while(p!=NULL&&p->ch>=32&&p->ch<127&&p->ch!=13&&p->ch!=-1) /*指针p不能为空,且数据域必须为常规字符*/{putch(p->ch);/*在文本窗口中输出该字符*/p=p->next; /*指向下一个节点*/}q=q->nextl; /*指向下一个节点*/if((p->ch==13||p->ch==-1)&&q!=NULL) gotoxy(1,wherey()+1); /*若ch为回车或EOF标记,光标跳至下行的开始处*/}while(q!=NULL); /*逐行逐列显示文本字符*/}void control(int A, Hnode *Hhead){void colorview(Hnode *,int,int); /*函数声明*/int x,y,flag=0;x=wherex(); y=wherey(); /*得到当前光标的坐标值*/if((A==CL)&&(x!=1)) /*ctrl+←,当前光标不是在行首,光标移动*/gotoxy(wherex()-1,wherey());if((A==CL)&&(x==1)) /*ctrl+←,在行首*/gotoxy(abs(judge(Hhead,wherey()-1)),wherey()-1); /*judge(Hhead,wherey()-1)上一行的字符个数作为x值,光标移动*/if((A==CR)&&check(Hhead,wherey(),wherex())>0) /*ctrl+→,当前光标的右边有字符,光标移动*/{ flag=1; gotoxy(wherex()+1,wherey()); }if((A==CR)&&check(Hhead,wherey()+1,1)>0&&check(Hhead,y,x)==0) /*ctrl+→,当前光标处没有字符但下一行的第一列有字符,光标移动*/{ flag=1; gotoxy(1,wherey()+1); }if((A==CR)&&x==80) /*ctrl+→,当前光标在当前行的行尾,光标移动*/{ flag=1; gotoxy(1,wherey()+1); }if(A==CR&&flag==1) /*ctrl+→,光标已经跳至新处,将当前光标所在位置的字符的坐标和值保存在r数组中*/{r[abs(value)].col=wherex();r[abs(value)].line=wherey();r[abs(value)].ch=check(Hhead,r[abs(value)].line,r[abs(value)].col);if(r[abs(value)].ch==-1) r[abs(value)].ch=13; /*若第line行,第col列的字符为回车键,则返回-1*/value--;}if(A==CL&&(x!=1||y!=1)) /*ctrl+←,当前光标并不在窗口左上角,将当前光标所在位置的字符的坐标和值保存在r数组中*/{r[abs(value)].col=wherex();r[abs(value)].line=wherey();r[abs(value)].ch=check(Hhead,r[abs(value)].line,r[abs(value)].col);value++;}colorview(Hhead,wherex(),wherey());}/*用不同的前背景色显示选择的字符*/void colorview(Hnode *Hhead,int x,int y){int i;view(Hhead);/*重新显示所有文本字符*/for(i=0;i<abs(value);i++) /*value为数组下标*/{gotoxy(r[i].col,r[i].line);textcolor(0);textbackground(7);cprintf("%c",r[i].ch);}textcolor(7);textbackground(0);gotoxy(x,y);}int check(Hnode *Hhead,int m,int n) /*check():在单链表中检查第m行第n列位置的字符,若为常规字符,则返回该字符*/{int i;Hnode *q;node *p;q=Hhead;for(i=1;i<m;i++) /*定位至行单链表中的第m个元素*/q=q->nextl;p=q->next;/*获取第m个节点的数据域*/for(i=1;i<n;i++) /*定位至列单链表中的第n个元素*/p=p->next;if(p->ch==13) return -1; /*若第m行,第n列的字符为回车键,则返回-1*/if(p->ch>=32&&p->ch<127) return p->ch; /*若第m行,第n列的字符为常规字符,则返回该字符*/else return 0; /*若第m行,第又非常规字符,则返回0*/}int judge(Hnode *Hhead,int m) /*judge():返回第m行中的常规字符总的个数,不包括回车符*/ {Hnode *q;node *p;int i,num=0;q=Hhead;for(i=1;i<m;i++) /*定位至行单链表中的第m个元素*/q=q->nextl;if(q==NULL) return -1; /*返回-1,表示第m行不存在*/p=q->next;while(p->next!=NULL){p=p->next;num++; /*统计第m行的字符个数*/}/*行尾字符还没有判断,接下来判断行尾字符*/if(p->ch==13&&num==0) return 0; /*返回0,表示当前行只有一个回车字符*/if(p->ch>=32&&p->ch<127) return num+1; /*返回num+1,表示当前行的最后一个字符为常规字符*/if(p->ch==13&&num!=0) return num; /*返回num,表示当前行的最后一个字符为回车符,不计算在内*/else return num;/*返回num,表示当前行中只有一个字符,且没有回车符*/}int del(Hnode *Hhead,int m,int n) /*del():删除第m行,第n列位置的字符*/{Hnode *q,*q1;node *p1,*p2,*tail;int i ,j,flag=0;q=Hhead;if(n==0&&m==1) return; /*第1行,第0列不存在*/if(n==0&&m>1) /*若为第0列字符,但行必须大于1,执行向上行移处理*/{m=m-1;gotoxy(judge(Hhead,wherey()-1)+1,m);/*移至第m-1行,第76列*/flag=1; /*移位的标志置1*/}for(i=1;i<m;i++) /*定位至行单链表中的第m个元素*/q=q->nextl;p1=q->next;for(i=1;i<n-1;i++) /*定位至列单链表中的第n-1个元素*/p1=p1->next;p2=p1->next; /*p2指向列单链表中的第n个元素*/if(n==1) /*若是删除第m行第1列的字符*/{q->next=p1->next;free(p1);}else{p1->next=p2->next; /*在单链表中删除第m行第n列的元素*/free(p2);}return flag; /*返回0:表示没有换位,返回1:表示有换位*/}void insert(Hnode *Hhead,int m,int n, char a) /*第m行,第n列的位置之前一个位置,插入单字符*/{int i;Hnode *q;node *p,*p1,*p2;q=Hhead;for(i=1;i<m;i++) /*定位至行单链表中的第m个元素*/q=q->nextl;p1=q->next;for(i=1;i<n-1;i++) /*定位至列单链表中的第n-1个元素*/p1=p1->next;p=(node *)malloc(sizeof(node)); /*创建一个新的列单链表节点*/p->ch=a; /*给此节点的数据域赋值*/if(n==1) /*插入之前,若只有一个字符在行中,则插在此节点之前*/{p->next=q->next;q->next=p;}else{p->next=p1->next; /*在第m行,第n列的字符前,插入一字符*/p1->next=p;}test(Hhead,m); /*在插入新元素后,检验并处理单链表中第m行开始的元素,使其满足规则*/}/*执行insert()后,检验第n行及后面的数据,使其满足规则*/int test(Hnode *Hhead,int n){int i=0;node *p1,*p2,*tail,*temp1,*temp2;Hnode *q,*q1;q=Hhead;for(i=1;i<n;i++) /*定位至行单链表中的第n个元素*/{q=q->nextl;}tail=p1=q->next;if(p1==NULL){return ; /*若此行没有任何字符,则返回*/}while(tail->next!=NULL) /*定位至列单链表中的最后一个元素*/{tail=tail->next;}for(i=1;i<80;i++){p1=p1->next;}p2=p1->next;p1->next=NULL; /*在此行的最后一个字符的前一个字符处断行,因为插入在此行插入了一个新的字符*/if(tail->ch!=13) /*若此行行尾不是回车键*/{if(q->nextl==NULL)/*若p1的数据域为回车符且行单链表中只有n个节点*/{q1=(Hnode *)malloc(sizeof(Hnode));q1->nextl=NULL;q1->next=p2; /*新行单链表节点保存此行多出的字符*/q->nextl=q1;}else{q=q->nextl;tail->next=q->next;/*将多出的字符与下一行的字符相连*/q->next=p2;test(Hhead,++n);}}else{q1=(Hnode *)malloc(sizeof(Hnode));q1->nextl=q->nextl;q1->next=p2;q->nextl=q1;}}/*从任意文本文件中读取文件内容,保存至行单链表和列单链表形式的数据结构中*/void opens(Hnode *Hp){FILE* fp;Hnode *q11,*q22;node *p11,*p22,*hp;char temp;int count=0,flags=1;char filename[10]; /*保存文件名*/clrscr();/*清屏*/printf("Enter infile name,for example [c:\\wb.txt]:");/*输入文件名格式*/scanf("%s",filename); /*输入文件名*/fp=fopen(filename,"r");/*以只读方式打开文件,filename必须要存在*/if(fp==NULL)/*打开文件失败*/{textbackground(2);textcolor(13);cprintf("open file error!");getchar();exit(0) ;}q11=Hp;while(!feof(fp)){count=0;flags=1;q22=(Hnode *)malloc(sizeof(Hnode));/*新建一个行单链表中的节点*/p11=(node *)malloc(sizeof(node)); /*新建一个列单链表中的节点*/while((temp=fgetc(fp))!=10&&count<=80&&!feof(fp)) /*循环结束,表示在单链表中一行处理完毕,开始新行*/{p22=(node *)malloc(sizeof(node));/*新建一个列单链表中的节点*/if(flags==1){hp=p22;flags=0;} /*hp保存列单链表中的首节点的地址*/p22->ch=temp;p22->next=NULL;p11->next=p22;p11=p22;count++;}if(temp==10){ /*若为换行符,将其转换为回车符,因为在程序中,是按回车符处理的*/ p22=(node *)malloc(sizeof(node));p22->ch=13;p22->next=NULL;p11->next=p22;p11=p22;}if(!feof(fp))/*若没此条件,文件最后一行会处理两次.*/{q22->next=hp;q22->nextl=NULL; /*将存储了字符的新列单链表与行单链表中的新节点建立关联*/q11->nextl=q22;q11=q22;}fclose(fp);Hp=Hp->nextl;/*因为Hp的所在节点的数据域为空,所以Hp=Hp->nextl*/return ;}/*将head所指的行单链表中所指的各个列单链表中的数据域的值写入文件,文件路径和文件名由用户指定*/void save(Hnode *head){FILE* fp;Hnode *q;node *p;char filename[10]; /*保存文件名*/q=head;clrscr();/*清屏*/printf("Enter infile name,for example [c:\\wb.txt]:");/*输入文件名格式*/scanf("%s",filename); /*输入文件名*/fp=fopen(filename,"w");if(fp==NULL) /*打开文件失败*/{printf("\n=====>open file error!\n");getchar();return ;}do{p=q->next; /*指向node类型的数据*/while(p!=NULL){if((int)p->ch==13)/*把回车转化为换行符*/{fputc('\n',fp);p=p->next;}else{fputc(p->ch, fp);p=p->next;}}q=q->nextl;}while(q!=NULL);fclose(fp); /*关闭此文件*/return ;void main(){char a;int i,A,x,y,flag=0,b,t;Hnode *Hhead,*q;node *p1,*p2;Hhead=q=(Hnode *)malloc(sizeof(Hnode)); /*为行单链表中首节点分配内存空间*/q->nextl=NULL;q->next=p1=p2=(node *)malloc(sizeof(node));p1->ch=13;p1->next=NULL;while(1){while(bioskey(1)==0) continue; /*等待用户按键*/a=A=bioskey(0); /*返回输入的字符的键值*/if(a>=32&&a<127) /*若输入为常规字符*/{if(check(Hhead,wherey(),wherex())<=0)/*当前位置没有字符且输入是常规字符,则执行添加字符操作*/{p2->ch=a;putch(a);if(wherex()-1==80){q->nextl=(Hnode *)malloc(sizeof(Hnode));q=q->nextl;q->nextl=NULL;q->next=NULL;p1=p2=q->next=(node *)malloc(sizeof(node));p1->ch=13;p1->next=NULL;gotoxy(1,wherey()+1);}else{p2->next=(node *)malloc(sizeof(node));p2=p2->next;p2->ch=13;p2->next=NULL;}}else /*当前位置有字符且输入是常规字符,则执行插入字符操作*/{x=wherex();y=wherey();insert(Hhead,wherey(),wherex(),a);view(Hhead);gotoxy(x+1,y);}}if(a==13){gotoxy(1,wherey()+1);q->nextl=(Hnode *)malloc(sizeof(Hnode));q=q->nextl;q->nextl=NULL;q->next=NULL;p1=p2=q->next=(node *)malloc(sizeof(node));p1->ch=13;p1->next=NULL;}x=wherex(); y=wherey();/*文本窗口中左移,当前光标不在窗口的第1列*/if((A==LEFT)&&(x!=1))gotoxy(wherex()-1,wherey());/*文本窗口中左移,当前光标在窗口的第1列*/if((A==LEFT)&&(x==1))gotoxy(abs(judge(Hhead,wherey()-1)),wherey()-1);/*文本窗口中右移,若当前光标的右边一位有字符*/if((A==RIGHT)&&check(Hhead,wherey(),wherex())>0)gotoxy(wherex()+1,wherey());/*文本窗口中右移至下行的第1列,若当前光标位置没有字符且下行的第1列有字符*/if((A==RIGHT)&&check(Hhead,wherey()+1,1)!=0&&check(Hhead,y,x)<=0)gotoxy(1,wherey()+1);/*右移*/if((A==RIGHT)&&x==80)gotoxy(1,wherey()+1);/*上移*/if((A==UP)&&check(Hhead,wherey()-1,wherex())!=0)gotoxy(wherex(),wherey()-1);/*下移*/if((A==DOWN)&&check(Hhead,wherey()+1,wherex())!=0) gotoxy(wherex(),wherey()+1);/*处理BackSpace键*/if(A==BACK) /*处理BackSpace键*/{flag=del(Hhead,wherey(),wherex()-1);x=wherex()-1;y=wherey();view(Hhead);if(flag==0){gotoxy(x,y);}if(flag==1){gotoxy(x+1,y);flag=0;}}/*处理Ctrl+x按键*//*处理Ctrl+x按键*/if(A==Cx&&value!=0){if(value>0){x=wherex();y=wherey();}Else{x=r[0].col;y=r[0].line;}for(i=0;i<abs(value);i++)del(Hhead,r[i].line,r[i].col);backup=value; /*保存r数组的有值元素的最大下标值*/value=0; /*此value为全局变量*/view(Hhead);gotoxy(x,y);}/*处理Ctrl+c按键*/if(A==Cc&&value!=0){x=wherex();y=wherey();backup=value;value=0; /*此value为全局变量*/view(Hhead);gotoxy(x,y);}/*处理Ctrl+v按键*/if(A==Cv&&backup!=0){x=wherex();y=wherey();if(backup<0) /*Ctrl+右移键选定的文本,贴切此当前位置*/ for(i=0;i<abs(backup);i++)insert(Hhead,y,x+i,r[i].ch);/*逐个插入*/ if(backup>0) /*Ctrl+左移键选定的文本,贴切此当前位置*/ for(i=0;i<backup;i++)insert(Hhead,y,x+i,r[backup-1-i].ch);view(Hhead);gotoxy(x,y);}/*处理Ctrl+左移键或右移键*/if(A==CL||A==CR) control(A,Hhead);if(A==F1){clrscr();/*清屏*/main();} /*新建文件*/if(A==F3){ /*打开文件*/Hhead=(Hnode *)malloc(sizeof(Hnode));opens(Hhead);getchar();clrscr();view(Hhead);}/*保存文件*/if(A==F2){save(Hhead);clrscr();cprintf("save successfully!");getch();view(Hhead);}}}七【上机实验中的其他它问题及心得】此编辑器主要采用的是用链表的作为他的存储结构,此编辑器用了三个结构体来分别存储行(主要作用是存储列单链表的首地址)、每列的字符还有存储复制、剪切的字符。
数据结构上机操作实验报告

实验一单链表的基本操作(必做)一、实验目的1.掌握单链表的存储、初始化、插入、删除等操作的程序实现。
2.加深对单链表基本概念,基本理论及相应算法的掌握与理解。
3.了解链表的处理方式,学习体会简单的单链表程序实现相关知识。
二、实验内容1.建立一个链表、设计链表的基本操作实现算法、输出一个链表表,调试并输出结果。
2.编写一个程序实现如下功能:让计算机产生出50个0~9之间的随机数并依次保存到单链表中;输出遍历单链表;从单链表中删除与给定值相等的所有结点;输出遍历单链表;输出单链表长度,调试并输出结果。
三、实验步骤1.定义一个链表结构体。
2.利用插入功能插入一个结点。
3.利用删除功能删除一个结点。
四、程序运行测试1.利用插入功能插入一个结点。
2.利用删除功能删除一个结点。
五、实验报告要求1.绘制链表操作实现的流程图。
2.详细给出程序运行测试结果(包括测试数据和测试结果)。
3.选试验步骤2-3中的任意一个,给出程序的详细注释。
4.参考程序中某一部分功能的改进(选做)5.实验心得与体会6.附录,实验用源程序六、参考源代码#include <iostream.h>#include <malloc.h>typedef struct LNode{int data;struct LNode *next;}Lnode, *LinkList;//假设下面的单链表均为带头结点。
void CreatLinkList(LinkList &L,int j){//建立一个单链表L,数据为整数,数据由键盘随机输入。
LinkList p,q;L=(LinkList )malloc(sizeof(Lnode));L->next=NULL;q=L;cout<<"在单链表内输入整数:"<<endl;for(int i=0;i<j;i++) p=(LinkList)malloc(sizeof(Lnode)); cin>>p->data;p->next=q->next;q->next=p;q=p; }int PrintLinkList(LinkList &L){//输出单链表L的数据元素LinkList p;p=L->next;if(L->next==NULL){cout<<"链表没有元素!"<<endl;return 0;}cout<<"单链表的数据元素为:";while(p){cout<<p->data<<" ";p=p->next;}cout<<endl;return 1;}void LinkListLengh(LinkList &L){//计算单链表L的数据元素个数。
(最新版)《数据结构》上机实验报告(模版)

成都信息工程学院计算机系课程实验报告实验课程:数据结构实验项目:数据结构综合设计之二叉树遍历算法指导教师:李莉丽学生姓名: 梅钲琪学生学号:班级:应用122实验地点: 6308实验时间:实验成绩:评阅老师:一【上机实验目的】1.掌握二叉树的概念,包括二叉树、满二叉树和完全二叉树的定义。
2.掌握二叉树的性质。
3.重点掌握二叉树的存储结构,包括二叉树顺序存储结构和链式存储结构。
4.重点掌握二叉树的基本运算和各种遍历算法的实现。
二【实验环境】PC机1台,,VC++6.0,easyX图形库三【上机实验内容】数据结构综合设计之二叉树遍历算法四【上机调试程序流程图】(用传统流程图的形式表示)程序开始建立空的根节点root输入字符c判断c是否为’#’是否Root->tag=c程序结束Root指向左孩子root=root->lchildRoot指向右孩子root=root->rchild以先序方式建立二叉树程序开始Root指向二叉树当前节点判断root是否为空是否打印当前结点的tag程序结束Root指向左孩子root=root->lchildRoot指向右孩子root=root->rchild递归前序遍历二叉树程序开始Root指向二叉树当前节点判断root是否为空是否Root指向左孩子root=root->lchild程序结束打印当前结点的tagRoot指向右孩子root=root->rchild递归中序遍历二叉树程序开始Root指向二叉树当前节点判断root是否为空是否Root指向左孩子root=root->lchild程序结束Root指向右孩子root=root->rchild打印当前结点的tag递归后序遍历二叉树Root 指向二叉树当前节点判断root 是否为空访问root ,并将root 进栈,然后root=root->lchild建立栈s否非递归前序遍历二叉树程序开始判断栈s 是否为NULLRoot 出栈,并且root=root->rchild结束是是否Root 指向二叉树当前节点判断root 是否为空将root 进栈,然后root=root->lchild建立栈s否非递归中序遍历二叉树程序开始判断栈s 是否为NULLRoot 出栈,并访问root,然后root=root->rchild结束是是否Root 指向二叉树当前节点判断root 是否为空将root 进栈,然后root=root->lchild 建立栈s否非递归后序遍历二叉树程序开始判断栈s 是否为NULLRoot 出栈结束是是否判断右孩子是否存在或者已经访问过访问root ,并标记已经访问,然后root 置空是Root 指向右孩子否root 指向当前结点判断root 是否为Root 入队并访问root左孩子入队程序开始否程序结束是层次遍历二叉树建立队列判断左孩子是否为空判断右孩子是否为空右孩子入队否否是是五【上机调试中出现的错误信息、错误原因及解决办法】非递归后序遍历时出现了问题,不能遍历非完全二叉树,后来用到,右孩子不存在或者已经访问过,root出栈并访问,否则,不出栈,继续访问右孩子层次遍历是开始想的是用栈来实现,但是很麻烦,还有问题,后来用队列,解决了问题六【上机调试后的源程序及还存在的问题】#include<stdio.h>#define MAXN 100#include<windows.h>#include<graphics.h>struct BTNode{char tag;BTNode *left;BTNode *right;};//二叉树结点int X[10]={ 75};int Y[10]={ 20};//动画演示的坐标char B[21]={'A','B','C','#','#','D','E','#','#','F','#','#','G','H','#','#','I','J','#','#','#'};//固定动画演示的char C[10]={'A','B','C','D','E','F','G','H','I','J'};int xx[10]={ 325};//输出结果的横坐标int flag=0;//标记是否进行动画演示,0 代表“不”,1 代表“要”void creatree(BTNode **root)//动画演示先序构造二叉树{static ii=0;if(B[ii] == '#'){*root=NULL;ii++;}else{*root = new BTNode;(*root)->tag = B[ii];ii++;creatree(&(*root)->left);creatree(&(*root)->right);}}/*先序方式创建二叉树*/void BuildBTree(BTNode **root){char c;c = getchar();if(c == '#')*root=NULL;else{*root = new BTNode;(*root)->tag = c;BuildBTree(&(*root)->left);BuildBTree(&(*root)->right);}}void PreVisit(BTNode *root)//递归前序遍历{static ii=0;if(root!=NULL){if (flag == 0)//不动画演示{printf("%c ", root->tag );}else//动画演示{for (int i=0;i<10;i++){if (C[i] == root->tag){setcolor(GREEN);fillcircle(X[i],Y[i],15);setcolor(GREEN);setbkmode(TRANSPARENT);setfont(20, 20,"宋体");outtextxy(X[i]-10, Y[i]-7,C[i]);setbkmode(OPAQUE);outtextxy(xx[ii], 400,C[i]);ii++;break;}}Sleep(1500);}PreVisit(root->left);PreVisit(root->right);}}void InVisit(BTNode *root)//递归中序遍历{static ii=0;if(root!=NULL){InVisit(root->left);if (flag == 0){printf("%c ", root->tag );}else{for (int i=0;i<10;i++){if (C[i] == root->tag){setcolor(500);fillcircle(X[i],Y[i],15);setcolor(500);setbkmode(TRANSPARENT);setfont(20, 20,"宋体");outtextxy(X[i]-10, Y[i]-7,C[i]);setbkmode(OPAQUE);outtextxy(xx[ii], 400,C[i]);ii++;break;}}Sleep(1500);}InVisit(root->right);}}void PostVisit(BTNode *root)//递归后序遍历{static ii=0;if(root!=NULL){PostVisit(root->left);PostVisit(root->right);if (flag == 0){printf("%c ", root->tag );}else{for (int i=0;i<10;i++){if (C[i] == root->tag){setcolor(GREEN);fillcircle(X[i],Y[i],15);setcolor(GREEN);setbkmode(TRANSPARENT);setfont(20, 20,"宋体");outtextxy(X[i]-10, Y[i]-7,C[i]);setbkmode(OPAQUE);outtextxy(xx[ii], 400,C[i]);ii++;break;}}Sleep(1500);}}}void NR_PreVisit(BTNode *root)//非递归前序遍历{BTNode *s[MAXN]; //栈int top=0; //头指针while(top!=0 ||root!=NULL) //如果结点不为空或栈不为空{while(root!=NULL) //如果结点不为空{s[top] = root; //压栈printf("%c ", s[top]->tag); //输出结点top++;root = root->left; //指向左孩子}if(top>0)//如果栈不为空{top--; //出栈root = s[top];root = root->right;//指向右孩子}}}void NR_InVisit(BTNode *root)//非递归中序遍历{BTNode *s[MAXN]; //栈int top=0; //头指针while(top!=0 || root!=NULL) //如果结点不为空或栈不为空{while(root!=NULL)//如果结点不为空{s[top++]=root;//压栈root = root->left; //指向左孩子}if(top>0)//如果栈不为空{root = s[--top];printf("%c ", root->tag);root = root->right;}}}void NR_PostVisit(BTNode *root)//非递归后序遍历{BTNode *s[MAXN], *tmp=NULL;int top=0;while(top!=0 || root!=NULL){while(root!=NULL){s[top++]=root;root=root->left;}if(top>0){root = s[--top];/*右孩子不存在或者已经访问过,root出栈并访问*/if( (root->right == NULL) || (root->right == tmp) ){printf("%c ", root->tag);tmp = root; //保存root指针root=NULL; //当前指针置空,防止再次入栈}/*不出栈,继续访问右孩子*/else{top++; //与root=s[--top]保持平衡root = root->right;}}}}void Cengci(BTNode *root) /* 按层次遍历*/{static ii=0;BTNode *V[MAXN],*p;int front=0,area=0;//队列if (root!=NULL){area++;V[area]=root;while (front<area){front++;p=V[front];if (flag == 0){printf("%c ", p->tag);}else{for (int i=0;i<10;i++){if (C[i] == p->tag){setcolor(500);fillcircle(X[i],Y[i],15);setcolor(500);setbkmode(TRANSPARENT);setfont(20, 20,"宋体");outtextxy(X[i]-10, Y[i]-7,C[i]);setbkmode(OPAQUE);outtextxy(xx[ii], 400,C[i]);ii++;break;}}Sleep(1500);}if(p->left!=NULL){area++;V[area]=p->left;}if(p->right!=NULL){area++;V[area]=p->right;}}}return;}int main(){BTNode *root=NULL,*T=NULL;BuildBTree(&root); //头指针的地址/*非动画演示部分*/printf("递归前序遍历:");//递归遍历PreVisit(root);printf("\n");printf("递归中序遍历:");InVisit(root);printf("\n");printf("递归后序遍历:");PostVisit(root);printf("\n\n");printf("非递归前序遍历:");//非递归遍历NR_PreVisit(root);printf("\n");printf("非递归中序遍历:");NR_InVisit(root);printf("\n");printf("非递归后序遍历:");NR_PostVisit(root);printf("\n\n");printf("层次遍历:");//层次遍历Cengci(root);printf("\n\n");printf("\n\n按任意键进行特例动画演示。
数据结构上机实验报告

数据结构上机实验报告学院:电子工程学院专业:信息对抗技术姓名:学号:教师:饶鲜日期:目录实验一线性表 ........................................................................................................ - 4 -一、实验目的.................................................................................................... - 4 -二、实验代码.................................................................................................... - 4 -三、实验结果.................................................................................................. - 14 -四、个人思路.................................................................................................. - 15 - 实验二栈和队列 .................................................................................................. - 15 -一、实验目的.................................................................................................. - 15 -二、实验代码.................................................................................................. - 16 -三、实验结果.................................................................................................. - 24 -四、个人思路.................................................................................................. - 25 - 实验三数组 .......................................................................................................... - 26 -一、实验目的.................................................................................................. - 26 -二、实验代码.................................................................................................. - 26 -三、实验结果.................................................................................................. - 28 -四、个人思路.................................................................................................. - 28 - 实验四树 .............................................................................................................. - 29 -一、实验目的.................................................................................................. - 29 -二、实验代码.................................................................................................. - 29 -三、实验结果.................................................................................................. - 39 -四、个人思路.................................................................................................. - 39 -实验一线性表一、实验目的1.熟悉线性表的顺序和链式存储结构2.掌握线性表的基本运算3.能够利用线性表的基本运算完成线性表应用的运算二、实验代码1.设有一个线性表E={e1, e2, … , e n-1, e n},设计一个算法,将线性表逆置,即使元素排列次序颠倒过来,成为逆线性表E’={ e n, e n-1 , … , e2 , e1 },要求逆线性表占用原线性表空间,并且用顺序表和单链表两种方法表示,分别用两个程序来完成。
数据结构上机实习报告

上机实习报告班号:116112姓名:**学号:***********实习报告【实习一】线性表及其应用n(n>20)的阶乘【问题描述】大数运算——计算n的阶乘(n>=20)。
【基本要求】(1)数据的表示和存储:(1.1)累积运算的中间结果和最终的计算结果的数据类型要求是整型——这是问题本身的要求;(1.2)试设计合适的存储结构,要求每个元素或结点最多存储数据的3位数值。
(2)数据的操作及其实现:基于设计的存储结构实现乘法操作,要求从键盘上输入n值,在屏幕上显示最终计算结果。
【问题分析】(1)设计数据的存储结构:介于乘运算的精确性以及实型数据表示的不精确性,本题不能采用实型表示累积运算的中间结果和最终的计算结果,而只能用整型。
然而由于普通整型和长整型所能表述数的范围受其字长的限制,不能表示大数阶乘的累积结果,故必须设计一个合适的数据结构实现对数据的存储,例如可以让每个元素或结点存储数据的若干位数值。
从问题描述不难看出n值为任意值,故为使程序尽量不受限制,应采用动态存储结构。
累积运算的特点是当前的计算结果是下次乘法运算的乘数。
实现两个数的乘法运算须考虑:(1)乘数的各位数都要与被乘数进行乘法运算;(2)乘法过程中的进位问题及其实现;(3)因每个元素或结点最多存储数据的3位数值,故当元素或结点中的数值大于999,需向前一个元素或结点进位。
综合以上几点,我采用了单链表的储存结构形式。
(2)阶乘算法的实现:1. 链表型数据乘法的具体实现描述:(1)初始算法顺序访问对每个节点上的数据乘以要乘的数后在顺序访问查看是否需要进位,大于999则向前进位,如果前面没有节点则添加新节点储存进位的数(2)改进算法将原始算法的乘操作和进位操作合在一起进行,提高程序效率.2. 数据输出算法具体实现描述从高位向低位顺序输出节点上储存的数据,注意补零,最高位的节点不补,其它节点要补。
对于最后的结果,因为我采用的是普通的单链表算法,因此我添加了一个逆置的算法。
数据结构上机实验报告

数据结构上机实验报告数据结构上机实验报告1. 实验目的数据结构是计算机科学中非常重要的一门课程,通过本次上机实验,旨在帮助学生巩固和应用所学的数据结构知识,培养学生分析和解决实际问题的能力。
2. 实验背景本次实验涉及到两个常用的数据结构:栈和队列。
栈是一种后进先出(Last In First Out,LIFO)的数据结构,而队列是一种先进先出(First In First Out,FIFO)的数据结构。
通过实验,我们将学习如何使用这两种数据结构来解决实际问题。
3. 实验内容本次实验分为两个部分:栈的应用和队列的应用。
3.1 栈的应用在栈的应用部分,我们将实现一个简单的括号匹配算法。
该算法可以判断一个字符串中的括号是否匹配。
具体实现步骤如下:3.1.1 创建一个栈来存储括号字符;3.1.2 遍历字符串中的每个字符;3.1.3 如果遇到左括号,则将其入栈;3.1.4 如果遇到右括号,则判断栈顶元素是否是对应的左括号;3.1.5 如果栈为空或栈顶元素不是对应的左括号,则括号不匹配;3.1.6 如果栈顶元素是对应的左括号,则将其出栈;3.1.7 遍历完字符串后,如果栈为空,则括号匹配,否则括号不匹配。
通过实现这个算法,我们可以学习到如何使用栈来解决实际问题,并且理解栈的后进先出的特性。
3.2 队列的应用在队列的应用部分,我们将实现一个简单的任务调度算法。
该算法可以模拟多个任务按照一定的优先级进行调度的过程。
具体实现步骤如下:3.2.1 创建一个队列来存储任务;3.2.2 每个任务包含两个属性:任务名称和优先级;3.2.3 向队列中添加任务,并按照优先级进行排序;3.2.4 从队列中取出优先级最高的任务,并执行;3.2.5 执行完任务后,继续从队列中取出下一个优先级最高的任务,并执行,直到队列为空。
通过实现这个算法,我们可以学习到如何使用队列来实现任务调度,并且理解队列的先进先出的特性。
4. 实验结果与分析通过实验,我们成功实现了括号匹配算法和任务调度算法,并得到了正确的结果。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
成都信息工程学院计算机系课程实验报告一【上机实验目的】要求功能与界面模拟WINDOWS记事本,支持鼠标,因为记事本功能较多,可以根据自己的能力模拟出部分功能,文本编辑这部分功能必须实现,主要利用串的知识。
二【实验环境】PC机每人1台三【上机实验内容】要求功能与界面模拟WINDOWS记事本,支持鼠标,因为记事本功能较多,可以根据自己的能力模拟出部分功能,文本编辑这部分功能必须实现,主要利用串的知识。
四【上机调试程序流程图】(注:可打印)在此程序中,主要包含了添加、插入、删除、复制、剪切、粘贴、还有文件操作。
五【上机调试中出现的错误信息、错误原因及解决办法】1、开始的时候当我输入字符的时候,总是输不进去,经过检查才知道,我忘了把字符输出到屏幕上。
2、在删除的时候,当一行删除完的时候,光标并不会上移到上一行。
然后我通过判断当这光标处的坐标减一后为零(表示这行没有字符了)的时候,然后重新读取光标,让光标显示在上一行。
3、在进行插入操作之后,移动光标会出现问题,就好像插入的字符并没有在链表当中一样。
然后我写了一个测试函数,来判断插入后链表是否满足每列的字符数不得超过80个字符。
然后让每列的字符数都在链表当中,满足要求。
六【上机调试后的源程序及还存在的问题】(注:源程序可打印)/*文本编辑器editor源代码*/#include <stdio.h>#include <conio.h>#include <bios.h>#include <math.h>#define LEFT 0x4b00 /*←:光标左移*/#define RIGHT 0x4d00 /*→:光标右移*/#define DOWN 0x5000 /*↓键:光标下移*/#define UP 0x4800 /*↑键:光标上移*/#define ESC 0x011b /*ESC键:取消菜单打开操作*/#define ENTER 0x1c0d /*回车键:换行*/#define BACK 3592 /*BackSpace键:删除当前光标位置前一个字符*/#define CL 29440 /*ctrl+←键:从右至左,选定文本*/#define CR 29696 /*ctrl+→键:从左到右,选定文本*/#define Cc 11779 /*ctrl+c键:将选定文本,复制一份到剪贴板中*/#define Cv 12054 /*ctrl+v键:将剪贴板中的内容复制到当前位置*/#define Cx 11544 /*ctrl+x键:对选定文本,执行剪切操作*/#define F1 15104 /*F1键:打开文件菜单*/#define F2 15360 /*F2键:打开编辑菜单*/#define F3 15616 /*F3键:打开帮助菜单*/int value,backup;/*value保存有值数组元素的最大下标值,backup保存value的副本,NUM保存当前行中的用户输入的字符个数*/typedef struct record{char ch; /*保存一字符*/int col, line; /*x轴和y轴坐标*/}record;record r[500]; /*定义一个有500个元素的结构体数组,保存选定的文本字符的属性*/typedef struct node /*定义保存行中的单个字符的结构*/{char ch; /*数据域:保存一字符*/struct node *next; /*指针域:指向下一个结点的指针*/}node;/*由此类型节点构成的单链表,命名为:列单链表*/typedef struct Hnode /*定义保存所有列单链表首节点的指针的结构*/{node *next; /*指向列单链表的首节点的地址*/struct Hnode *nextl; /*指向下一个节点的指针*/}Hnode;/*由此类型节点构成的单链表,命名为:行单链表*/void view(Hnode *q) /*按行显示保存在单链表中的文本字符,q为指向行单链表中第一个节点的指针*/{node *p; /*p为保存列单链表节点元素地址的指针*/clrscr(); /*清屏*//*双重循环,读取并显示保存在单链表中字符*/do{p=q->next;while(p!=NULL&&p->ch>=32&&p->ch<127&&p->ch!=13&&p->ch!=-1) /*指针p不能为空,且数据域必须为常规字符*/{putch(p->ch);/*在文本窗口中输出该字符*/p=p->next; /*指向下一个节点*/}q=q->nextl; /*指向下一个节点*/if((p->ch==13||p->ch==-1)&&q!=NULL) gotoxy(1,wherey()+1); /*若ch为回车或EOF标记,光标跳至下行的开始处*/}while(q!=NULL); /*逐行逐列显示文本字符*/}void control(int A, Hnode *Hhead){void colorview(Hnode *,int,int); /*函数声明*/int x,y,flag=0;x=wherex(); y=wherey(); /*得到当前光标的坐标值*/if((A==CL)&&(x!=1)) /*ctrl+←,当前光标不是在行首,光标移动*/gotoxy(wherex()-1,wherey());if((A==CL)&&(x==1)) /*ctrl+←,在行首*/gotoxy(abs(judge(Hhead,wherey()-1)),wherey()-1); /*judge(Hhead,wherey()-1)上一行的字符个数作为x值,光标移动*/if((A==CR)&&check(Hhead,wherey(),wherex())>0) /*ctrl+→,当前光标的右边有字符,光标移动*/{ flag=1; gotoxy(wherex()+1,wherey()); }if((A==CR)&&check(Hhead,wherey()+1,1)>0&&check(Hhead,y,x)==0) /*ctrl+→,当前光标处没有字符但下一行的第一列有字符,光标移动*/{ flag=1; gotoxy(1,wherey()+1); }if((A==CR)&&x==80) /*ctrl+→,当前光标在当前行的行尾,光标移动*/{ flag=1; gotoxy(1,wherey()+1); }if(A==CR&&flag==1) /*ctrl+→,光标已经跳至新处,将当前光标所在位置的字符的坐标和值保存在r数组中*/{r[abs(value)].col=wherex();r[abs(value)].line=wherey();r[abs(value)].ch=check(Hhead,r[abs(value)].line,r[abs(value)].col);if(r[abs(value)].ch==-1) r[abs(value)].ch=13; /*若第line行,第col列的字符为回车键,则返回-1*/value--;}if(A==CL&&(x!=1||y!=1)) /*ctrl+←,当前光标并不在窗口左上角,将当前光标所在位置的字符的坐标和值保存在r数组中*/{r[abs(value)].col=wherex();r[abs(value)].line=wherey();r[abs(value)].ch=check(Hhead,r[abs(value)].line,r[abs(value)].col);value++;}colorview(Hhead,wherex(),wherey());}/*用不同的前背景色显示选择的字符*/void colorview(Hnode *Hhead,int x,int y){int i;view(Hhead);/*重新显示所有文本字符*/for(i=0;i<abs(value);i++) /*value为数组下标*/{gotoxy(r[i].col,r[i].line);textcolor(0);textbackground(7);cprintf("%c",r[i].ch);}textcolor(7);textbackground(0);gotoxy(x,y);}int check(Hnode *Hhead,int m,int n) /*check():在单链表中检查第m行第n列位置的字符,若为常规字符,则返回该字符*/{int i;Hnode *q;node *p;q=Hhead;for(i=1;i<m;i++) /*定位至行单链表中的第m个元素*/q=q->nextl;p=q->next;/*获取第m个节点的数据域*/for(i=1;i<n;i++) /*定位至列单链表中的第n个元素*/p=p->next;if(p->ch==13) return -1; /*若第m行,第n列的字符为回车键,则返回-1*/if(p->ch>=32&&p->ch<127) return p->ch; /*若第m行,第n列的字符为常规字符,则返回该字符*/else return 0; /*若第m行,第又非常规字符,则返回0*/}int judge(Hnode *Hhead,int m) /*judge():返回第m行中的常规字符总的个数,不包括回车符*/ {Hnode *q;node *p;int i,num=0;q=Hhead;for(i=1;i<m;i++) /*定位至行单链表中的第m个元素*/q=q->nextl;if(q==NULL) return -1; /*返回-1,表示第m行不存在*/p=q->next;while(p->next!=NULL){p=p->next;num++; /*统计第m行的字符个数*/}/*行尾字符还没有判断,接下来判断行尾字符*/if(p->ch==13&&num==0) return 0; /*返回0,表示当前行只有一个回车字符*/if(p->ch>=32&&p->ch<127) return num+1; /*返回num+1,表示当前行的最后一个字符为常规字符*/if(p->ch==13&&num!=0) return num; /*返回num,表示当前行的最后一个字符为回车符,不计算在内*/else return num;/*返回num,表示当前行中只有一个字符,且没有回车符*/}int del(Hnode *Hhead,int m,int n) /*del():删除第m行,第n列位置的字符*/{Hnode *q,*q1;node *p1,*p2,*tail;int i ,j,flag=0;q=Hhead;if(n==0&&m==1) return; /*第1行,第0列不存在*/if(n==0&&m>1) /*若为第0列字符,但行必须大于1,执行向上行移处理*/{m=m-1;gotoxy(judge(Hhead,wherey()-1)+1,m);/*移至第m-1行,第76列*/flag=1; /*移位的标志置1*/}for(i=1;i<m;i++) /*定位至行单链表中的第m个元素*/q=q->nextl;p1=q->next;for(i=1;i<n-1;i++) /*定位至列单链表中的第n-1个元素*/p1=p1->next;p2=p1->next; /*p2指向列单链表中的第n个元素*/if(n==1) /*若是删除第m行第1列的字符*/{q->next=p1->next;free(p1);}else{p1->next=p2->next; /*在单链表中删除第m行第n列的元素*/free(p2);}return flag; /*返回0:表示没有换位,返回1:表示有换位*/}void insert(Hnode *Hhead,int m,int n, char a) /*第m行,第n列的位置之前一个位置,插入单字符*/{int i;Hnode *q;node *p,*p1,*p2;q=Hhead;for(i=1;i<m;i++) /*定位至行单链表中的第m个元素*/q=q->nextl;p1=q->next;for(i=1;i<n-1;i++) /*定位至列单链表中的第n-1个元素*/p1=p1->next;p=(node *)malloc(sizeof(node)); /*创建一个新的列单链表节点*/p->ch=a; /*给此节点的数据域赋值*/if(n==1) /*插入之前,若只有一个字符在行中,则插在此节点之前*/{p->next=q->next;q->next=p;}else{p->next=p1->next; /*在第m行,第n列的字符前,插入一字符*/p1->next=p;}test(Hhead,m); /*在插入新元素后,检验并处理单链表中第m行开始的元素,使其满足规则*/}/*执行insert()后,检验第n行及后面的数据,使其满足规则*/int test(Hnode *Hhead,int n){int i=0;node *p1,*p2,*tail,*temp1,*temp2;Hnode *q,*q1;q=Hhead;for(i=1;i<n;i++) /*定位至行单链表中的第n个元素*/{q=q->nextl;}tail=p1=q->next;if(p1==NULL){return ; /*若此行没有任何字符,则返回*/}while(tail->next!=NULL) /*定位至列单链表中的最后一个元素*/{tail=tail->next;}for(i=1;i<80;i++){p1=p1->next;}p2=p1->next;p1->next=NULL; /*在此行的最后一个字符的前一个字符处断行,因为插入在此行插入了一个新的字符*/if(tail->ch!=13) /*若此行行尾不是回车键*/{if(q->nextl==NULL)/*若p1的数据域为回车符且行单链表中只有n个节点*/{q1=(Hnode *)malloc(sizeof(Hnode));q1->nextl=NULL;q1->next=p2; /*新行单链表节点保存此行多出的字符*/q->nextl=q1;}else{q=q->nextl;tail->next=q->next;/*将多出的字符与下一行的字符相连*/q->next=p2;test(Hhead,++n);}}else{q1=(Hnode *)malloc(sizeof(Hnode));q1->nextl=q->nextl;q1->next=p2;q->nextl=q1;}}/*从任意文本文件中读取文件内容,保存至行单链表和列单链表形式的数据结构中*/void opens(Hnode *Hp){FILE* fp;Hnode *q11,*q22;node *p11,*p22,*hp;char temp;int count=0,flags=1;char filename[10]; /*保存文件名*/clrscr();/*清屏*/printf("Enter infile name,for example [c:\\wb.txt]:");/*输入文件名格式*/scanf("%s",filename); /*输入文件名*/fp=fopen(filename,"r");/*以只读方式打开文件,filename必须要存在*/if(fp==NULL)/*打开文件失败*/{textbackground(2);textcolor(13);cprintf("open file error!");getchar();exit(0) ;}q11=Hp;while(!feof(fp)){count=0;flags=1;q22=(Hnode *)malloc(sizeof(Hnode));/*新建一个行单链表中的节点*/p11=(node *)malloc(sizeof(node)); /*新建一个列单链表中的节点*/while((temp=fgetc(fp))!=10&&count<=80&&!feof(fp)) /*循环结束,表示在单链表中一行处理完毕,开始新行*/{p22=(node *)malloc(sizeof(node));/*新建一个列单链表中的节点*/if(flags==1){hp=p22;flags=0;} /*hp保存列单链表中的首节点的地址*/p22->ch=temp;p22->next=NULL;p11->next=p22;p11=p22;count++;}if(temp==10){ /*若为换行符,将其转换为回车符,因为在程序中,是按回车符处理的*/ p22=(node *)malloc(sizeof(node));p22->ch=13;p22->next=NULL;p11->next=p22;p11=p22;}if(!feof(fp))/*若没此条件,文件最后一行会处理两次.*/{q22->next=hp;q22->nextl=NULL; /*将存储了字符的新列单链表与行单链表中的新节点建立关联*/q11->nextl=q22;q11=q22;}fclose(fp);Hp=Hp->nextl;/*因为Hp的所在节点的数据域为空,所以Hp=Hp->nextl*/return ;}/*将head所指的行单链表中所指的各个列单链表中的数据域的值写入文件,文件路径和文件名由用户指定*/void save(Hnode *head){FILE* fp;Hnode *q;node *p;char filename[10]; /*保存文件名*/q=head;clrscr();/*清屏*/printf("Enter infile name,for example [c:\\wb.txt]:");/*输入文件名格式*/scanf("%s",filename); /*输入文件名*/fp=fopen(filename,"w");if(fp==NULL) /*打开文件失败*/{printf("\n=====>open file error!\n");getchar();return ;}do{p=q->next; /*指向node类型的数据*/while(p!=NULL){if((int)p->ch==13)/*把回车转化为换行符*/{fputc('\n',fp);p=p->next;}else{fputc(p->ch, fp);p=p->next;}}q=q->nextl;}while(q!=NULL);fclose(fp); /*关闭此文件*/return ;void main(){char a;int i,A,x,y,flag=0,b,t;Hnode *Hhead,*q;node *p1,*p2;Hhead=q=(Hnode *)malloc(sizeof(Hnode)); /*为行单链表中首节点分配内存空间*/q->nextl=NULL;q->next=p1=p2=(node *)malloc(sizeof(node));p1->ch=13;p1->next=NULL;while(1){while(bioskey(1)==0) continue; /*等待用户按键*/a=A=bioskey(0); /*返回输入的字符的键值*/if(a>=32&&a<127) /*若输入为常规字符*/{if(check(Hhead,wherey(),wherex())<=0)/*当前位置没有字符且输入是常规字符,则执行添加字符操作*/{p2->ch=a;putch(a);if(wherex()-1==80){q->nextl=(Hnode *)malloc(sizeof(Hnode));q=q->nextl;q->nextl=NULL;q->next=NULL;p1=p2=q->next=(node *)malloc(sizeof(node));p1->ch=13;p1->next=NULL;gotoxy(1,wherey()+1);}else{p2->next=(node *)malloc(sizeof(node));p2=p2->next;p2->ch=13;p2->next=NULL;}}else /*当前位置有字符且输入是常规字符,则执行插入字符操作*/{x=wherex();y=wherey();insert(Hhead,wherey(),wherex(),a);view(Hhead);gotoxy(x+1,y);}}if(a==13){gotoxy(1,wherey()+1);q->nextl=(Hnode *)malloc(sizeof(Hnode));q=q->nextl;q->nextl=NULL;q->next=NULL;p1=p2=q->next=(node *)malloc(sizeof(node));p1->ch=13;p1->next=NULL;}x=wherex(); y=wherey();/*文本窗口中左移,当前光标不在窗口的第1列*/if((A==LEFT)&&(x!=1))gotoxy(wherex()-1,wherey());/*文本窗口中左移,当前光标在窗口的第1列*/if((A==LEFT)&&(x==1))gotoxy(abs(judge(Hhead,wherey()-1)),wherey()-1);/*文本窗口中右移,若当前光标的右边一位有字符*/if((A==RIGHT)&&check(Hhead,wherey(),wherex())>0)gotoxy(wherex()+1,wherey());/*文本窗口中右移至下行的第1列,若当前光标位置没有字符且下行的第1列有字符*/if((A==RIGHT)&&check(Hhead,wherey()+1,1)!=0&&check(Hhead,y,x)<=0)gotoxy(1,wherey()+1);/*右移*/if((A==RIGHT)&&x==80)gotoxy(1,wherey()+1);/*上移*/if((A==UP)&&check(Hhead,wherey()-1,wherex())!=0)gotoxy(wherex(),wherey()-1);/*下移*/if((A==DOWN)&&check(Hhead,wherey()+1,wherex())!=0) gotoxy(wherex(),wherey()+1);/*处理BackSpace键*/if(A==BACK) /*处理BackSpace键*/{flag=del(Hhead,wherey(),wherex()-1);x=wherex()-1;y=wherey();view(Hhead);if(flag==0){gotoxy(x,y);}if(flag==1){gotoxy(x+1,y);flag=0;}}/*处理Ctrl+x按键*//*处理Ctrl+x按键*/if(A==Cx&&value!=0){if(value>0){x=wherex();y=wherey();}Else{x=r[0].col;y=r[0].line;}for(i=0;i<abs(value);i++)del(Hhead,r[i].line,r[i].col);backup=value; /*保存r数组的有值元素的最大下标值*/value=0; /*此value为全局变量*/view(Hhead);gotoxy(x,y);}/*处理Ctrl+c按键*/if(A==Cc&&value!=0){x=wherex();y=wherey();backup=value;value=0; /*此value为全局变量*/view(Hhead);gotoxy(x,y);}/*处理Ctrl+v按键*/if(A==Cv&&backup!=0){x=wherex();y=wherey();if(backup<0) /*Ctrl+右移键选定的文本,贴切此当前位置*/ for(i=0;i<abs(backup);i++)insert(Hhead,y,x+i,r[i].ch);/*逐个插入*/ if(backup>0) /*Ctrl+左移键选定的文本,贴切此当前位置*/ for(i=0;i<backup;i++)insert(Hhead,y,x+i,r[backup-1-i].ch);view(Hhead);gotoxy(x,y);}/*处理Ctrl+左移键或右移键*/if(A==CL||A==CR) control(A,Hhead);if(A==F1){clrscr();/*清屏*/main();} /*新建文件*/if(A==F3){ /*打开文件*/Hhead=(Hnode *)malloc(sizeof(Hnode));opens(Hhead);getchar();clrscr();view(Hhead);}/*保存文件*/if(A==F2){save(Hhead);clrscr();cprintf("save successfully!");getch();view(Hhead);}}}七【上机实验中的其他它问题及心得】此编辑器主要采用的是用链表的作为他的存储结构,此编辑器用了三个结构体来分别存储行(主要作用是存储列单链表的首地址)、每列的字符还有存储复制、剪切的字符。