赞
踩
软件技术(数据结构)所有主要程序-本人手写,均调试运行通过 数据结构主要程序: 顺序表、链表、二叉树、排序算法等 程序检查框架来源::段老师 内部程序算法:Marshal Zheng 程序文件名为table.cpp,源程序清单如下: /*******************************Copyright (c)********************************************* ** University of Electronic Science and Technology of China ** School of Communication and Information Engineering ** http://www.uestc.edu.cn ** **--------------------------- File Info --------------------------------------------------- ** File name: table.cpp ** Last modified Date: 2012-12-19 ** Last Version: 1.0 ** Descriptions: 各种顺序表操作,顺序表结构的定义在mystruct.h中, ** 函数中使用的与界面显示有关接口的说明在ui.h ** 本文件基于C语言风格 **------------------------------------------------------------------------------------------ ** Created by: Duan Jingshan ** Created date: 2012-12-19 **------------------------------------------------------------------------------------------ ** Modified by: ** Modified date: ** Version: ** Descriptions: ** *******************************************************************************************/ #include "stdafx.h" #include "mystruct.h" #include "ui.h" #include<stdlib.h> /******************************************************************************************* ** Function name: init_table() ** Descriptions : 初始化顺序表 ** 顺序表利用数组作为基础,其特点是需要事先获得全部元素空间,因此本函数的主要 ** 功能就是向系统申请足够的空间作为顺序表的存储空间。涉及的系统函数为: ** malloc() ** 此外,良好的习惯是将空间内的各项数据进行适当的初始化 ** Input: NONE ** Output: NONE ** return: 类型:table_t *,返回顺序表的结构指针 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ table_t * init_table() { table_t *t= (table_t *)malloc(sizeof(table_t)); t->length=0; if (t!=0) return t; else return NULL; } /******************************************************************************************* ** Function name: free_table() ** Descriptions : 释放顺序表空间 ** 当程序结束时会通过本函数来释放通过malloc获得的顺序表空间 ** Input: table_t * t; 顺序表指针 ** Output: NONE ** return: 类型:void ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ void free_table(table_t * t) { free(t); } /******************************************************************************************* ** Function name: get_table() ** Descriptions : 查询顺序表 ** 查询顺序表中第i个元素 ** Input: ** table_t * table; 顺序表指针 ** int index; 查询位置,即第i个元素 ** Output: ** element_t * elem; 元素域指针,用来存放被查询到的元素内容, ** (注意,需要将元素全部内容拷贝到该指针所记录的空间中,即,使用memcpy()) ** return: 类型:int,返回查询是否成功,为0表示找到指定元素,为-1表示没有找到,一般是因为 ** index指示的位置超出了顺序表的范围 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ int get_table(table_t * table,int index, element_t * elem) { //判断index是否超出顺序表范围 if(index <= 0 || index > table->length){ return -1; } //复制元素内容到指定空间中; memcpy(elem,&(table->data[index-1]),sizeof(element_t));//error return 0; } /******************************************************************************************* ** Function name: add_table() ** Descriptions : 将指定元素放入到顺序表的末尾 ** Input: ** table_t * table; 顺序表指针 ** element_t data; 待放入的元素 ** Output: ** table_t * table; 添加新元素后的顺序表指针 ** return: 类型:int; 为-1表示放入失败,一般是因为顺序表已经放满,为0表示正确放入 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ int add_table(table_t * table, element_t data) { if (table->length==MAX_TABLE_SIZE) return -1; else { table->data[table->length]=data; table->length++; return 0; } } /******************************************************************************************* ** Function name: insert_table() ** Descriptions : 将指定元素插入到顺序表的指定位置之前 ** Input: ** table_t * table; 顺序表指针 ** element_t data; 待放入的元素 ** int location; 插入位置,语义是:第X个元素前,,当location大于链表元素总数时,该元素 ** 将插入到表尾。 ** Output: ** table_t * table; 插入新元素后的顺序表指针 ** return: 类型:int; 为-1表示插入失败,一般是因为顺序表已经放满或者插入位置不正确, 为0表示正确插入 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ int insert_table(table_t * table, element_t data, int location) { int j=0; if (table->length>=MAX_TABLE_SIZE) return -1; else { if (location<=0) return -1; else if(location>table->length) { table->length++; table->data[table->length-1]=data; } else { for(j=table->length-1;j>=location-1;j--) { table->data[j+1]=table->data[j]; } table->data[location-1]=data; table->length++; } } return 0; } /******************************************************************************************* ** Function name: insert_table_by_order() ** Descriptions : 将指定元素按照学号从小到大顺序插入到顺序表中 ** Input: ** table_t * table; 顺序表指针 ** element_t data; 待放入的元素 ** Output: ** table_t * table; 插入新元素后的顺序表指针 ** return: 类型:int; 为-1表示插入失败,一般是因为顺序表已经放满或者插入位置不正确, 为0表示正确插入 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ int insert_table_by_order(table_t * table, element_t data) { int i=0,j=0,flag=0; element_t t; for(i=0;i<table->length;i++) { for(j=i;j<table->length-1;j++) { if(table->data[j].stuID>table->data[j+1].stuID) { t=table->data[j]; table->data[j]=table->data[j+1]; table->data[j+1]=t; } } } if (table->length>=MAX_TABLE_SIZE) return -1; else { for (i=0;i<table->length;i++) { if (data.stuID<table->data[i].stuID) { flag=i; break; } } for (j=table->length-1;j>=flag;j--) { table->data[j+1]=table->data[j]; } table->data[flag]=data; table->length++; } return 0; } /******************************************************************************************* ** Function name: delete_table() ** Descriptions : 删除顺序表中指定姓名作为关键字的元素 ** Input: ** table_t * table; 顺序表指针 ** char * name; 以该姓名为关键字的元素将被删除 ** Output: ** table_t * table; 删除指定元素后的顺序表指针 ** return: 类型:int; 为-1表示删除失败,一般是因为顺序表没有找到指定元素, 为0表示正确删除 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ int delete_table(table_t * table, char * name) { int i=0,j=0; int flag=table->length; for(i=0;i<table->length;i++) { if(strcmp(table->data[i].stuName,name)==0) { for(j=i+1;j<table->length;j++) { table->data[j-1]=table->data[j]; } table->length--; break; } } if(table->length==flag) return -1; else return 0; } /******************************************************************************************* ** Function name: delete_table_below() ** Descriptions : 删除顺序表中总分小于某个指定值的所有元素,本算法的特点是 ** 希望一趟能在顺序表中删除多个元素 ** Input: ** table_t * table; 顺序表指针 ** int x; 删除范围,即被删除的元素总分小于这个值 ** Output: ** table_t * table; 删除元素后的顺序表指针 ** return: 类型:void; ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ void delete_table_below(table_t * table, int x) { int i=0,j=0; for(i=0;i<table->length;i++) { if(table->data[i].overall>=x) { table->data[j]=table->data[i]; j++; } } table->length=j; } A、拓展训练ex1_2(1) 顺序表插入操作 程序流程说明: 初始化顺序表 ——> 自定义顺序表元素 ——> 顺序表元素排序(冒泡排序法) ——> 按从小到大的顺序插入元素 ——> 输出顺序表 程序文件名为ex1_1(顺序表插入),源程序清单如下: //by郑元帅 2016010901012 通信与信息工程学院 指导教师:居太亮 #include<stdio.h> struct Listt { int num; int data[100]; }listt; //模块化,子函数化 //初始化 自定义向量,包含向量长度(<0,=0,>0)判断报错 //返回值1或0,决定程序运行结束与否 //包含增序排序函数,冒泡排序法 ,可独立成子函数 int init(Listt *list) { int t=0; int i=0,j=0; printf("请输入向量的长度(>=0的自然数):"); scanf("%d",&list->num); if (list->num<0) { return 0; } else if(listt.num==0) { list->data[0]=NULL; return 1; } else { printf("请输入自定义向量元素(数字):\n"); for (i=0;i<list->num;i++) { scanf("%d",&list->data[i]); } for (j=0;j<list->num-1;j++) for (i=0;i<list->num-j-1;i++) { if (list->data[i]>list->data[i+1]) { t=list->data[i]; list->data[i]=list->data[i+1]; list->data[i+1]=t; } } printf("递增排序后的向量组:\n"); for (i=0;i<list->num;i++) { printf("%d\t",list->data[i]); } printf("\n"); return 1; } } // 插入函数,包含向量长度(=0,>0)判断,插入元素(数字)大小判断与位置标记flag //flag位置及之后向量元素后移一个单位 ,然后插入元素x,向量长度+1 void insertlist(Listt *l,int x) { int j=0,i=0; int flag=0; if(l->num==0) { l->data[0]=x; } for (i=0;i<l->num;i++) { if (x<l->data[i]) { flag=i; break; } } if (x>l->data[0]&flag==0) { l->num++; l->data[l->num-1]=x; } else { for (j=l->num-1;j>=flag;j--) { l->data[j+1]=l->data[j]; } l->data[flag]=x; l->num++; } } // 输出函数 void print_f(Listt *pl) { int i; for (i=0;i<pl->num;i++) { printf("%d\t",pl->data[i]); } } //主函数,包含错误判断 ,调用子函数 int main() { int x=0; if (init(&listt)==0) { printf("自定义向量长度错误!结束。"); return 0; } else { printf("\n请输入插入元素(数字):"); scanf("%d",&x); insertlist(&listt,x); printf("插入元素后的向量:\n"); print_f(&listt); } } B、拓展训练ex1_2(2) 顺序表删除负数 程序流程说明: 初始化顺序表 ——> 自定义顺序表元素 ——> 删除负数(依次将保留项向前覆盖) ——> 输出顺序表 ——> 退出程序 程序文件名为ex1_2(2)删除负数,源程序清单如下: //by郑元帅 2016010901012 通信与信息工程学院 指导教师:居太亮 #include<stdio.h> #include<stdlib.h> struct Listt { int num; int data[100]; }listt; //模块化,子函数化 //初始化 自定义向量 void init(Listt *list) { list->num=0; } //输入函数 ,自定义顺序表 void input_f(Listt *p) { int i=0; printf("请输入顺序表中元素个数:"); scanf("%d",&p->num); printf("请依次输入顺序表中的元素:\n"); for (i=0;i<p->num;i++) { scanf("%d",&p->data[i]); } } // 输出函数 void print_f(Listt *pl) { int i; for (i=0;i<pl->num;i++) { printf("%d\t",pl->data[i]); } } //删除负数 void delete_negative(Listt *p) { int i=0,j=0; for(i=0;i<p->num;i++) { if(p->data[i]>=0) { p->data[j]=p->data[i]; j++; } } p->num=j; } //主函数,包含错误判断 ,调用子函数 int main() { int x=0; init(&listt); input_f(&listt); delete_negative(&listt); if (listt.num==0) { printf("顺序表为空。"); return 0; } else { print_f(&listt); return 0; } } C、拓展训练ex1_2(3) 顺序表原表反序 程序流程说明: 初始化顺序表 ——> 自定义顺序表元素 ——> 选定旋转轴 ——> 原表上反序操作 ——> 输出顺序表 ——> 程序退出 程序文件名为ex1_2(2)删除负数,源程序清单如下: #include"stdio.h" #define M 100 struct list { int data[M]; int length; }ls; //初始化顺序表,自定义顺序表元素 int init(list *l) { int x=0,i=0; l->length=0; printf("请输入顺序表元素个数:"); scanf("%d",&l->length); if(l->length<=0) { return 0; } printf("请输入顺序表元素:\n"); for(i=0;i<l->length;i++) { scanf("%d",&x); l->data[i]=x; } printf("您输入的顺序表为:\n"); for(i=0;i<l->length;i++) { printf("%d\t",l->data[i]); } } //原表上反序操作 void reverse(list *l) { int i=0,k=0,t=0; k=(int)(l->length/2); for(i=0;i<k;i++) { t=l->data[i]; l->data[i]=l->data[l->length-1-i] ; l->data[l->length-1-i]=t; } } //输出函数 int printf_ls(list *l) { int i=0; printf("\n倒序后的顺序表为:\n"); for(i=0;i<l->length;i++) { printf("%d\t",l->data[i]); } } //主函数,判断初始化错误,调用子函数 int main() { if(init(&ls)==0) { printf("输入错误,顺序表为空或无定义,已退出"); return 0; } reverse(&ls); printf_ls(&ls); return 0; } 程序流程说明: 初始化链表,只需要为链表申请少量结构所需的空间即可。 ——> 将指定元素放入到链表的末尾。 ——> 查询链表中的第i个元素。 ——> 将指定元素插入到链表的指定位置之前。 ——> 将指定元素按照学号从小到大顺序插入到链表中(先冒泡排序,再插入) ——> 删除链表中指定姓名作为关键字的元素 ——> 删除链表中总分小于某个指定值的所有元素(一趟在链表中删除多个元素) ——> 释放存储空间,结束程序 程序文件名为link.cpp,源程序清单如下: /*******************************Copyright (c)********************************************* ** University of Electronic Science and Technology of China ** School of Communication and Information Engineering ** http://www.uestc.edu.cn ** **--------------------------- File Info --------------------------------------------------- ** File name: link.cpp ** Last modified Date: 2012-12-19 ** Last Version: 1.0 ** Descriptions: 各种链表操作,链表结构的定义在mystruct.h中, ** 函数中使用的与界面显示有关接口的说明在ui.h ** 本文件基于C语言风格 **------------------------------------------------------------------------------------------ ** Created by: Duan Jingshan ** Created date: 2012-12-19 **------------------------------------------------------------------------------------------ ** Modified by: ** Modified date: ** Version: ** Descriptions: ** *******************************************************************************************/ #include "stdafx.h" #include "mystruct.h" #include "ui.h" #include<stdio.h> #include<stdlib.h> /******************************************************************************************* ** Function name: init_link() ** Descriptions : 初始化链表 ** 链表的特点是利用内存离散空间存放各个元素,因此不必事先为链表准备足够大 ** 的内存空间,只是在需要插入新元素时,才申请必要的链点空间。因此在初始化 ** 链表时,只需要为链表申请少量结构所需的空间即可。 ** 关键是要将其中的头指针设置为空 ** Input: NONE ** Output: NONE ** return: 类型:link_t *,返回链表的结构指针 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ link_t * init_link() { link_t *li; li= (link_t *)malloc(sizeof(link_t)); li->head = NULL; li->length=0; return li; } /******************************************************************************************* ** Function name: free_link() ** Descriptions : 释放链表空间 ** 当程序结束时会通过本函数来释放链表空间,如果链表中还有元素,则需要逐个将 ** 元素的空间予以释放 ** Input: link_t * t; 链表结构指针 ** Output: NONE ** return: 类型:void ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ void free_link(link_t * t) { node_t * p; if(t == NULL){ return; } //如果链表中有链点,则需要逐个释放各链点空间,不能只是free(t); t->head=p; while(t->head != NULL){ p = t->head; t->head = t->head->next; free(p); } t->head = NULL; t->length = 0; free(t); } /******************************************************************************************* ** Function name: add_link() ** Descriptions : 将指定元素放入到链表的末尾 ** Input: ** link_t * link; 链表结构指针 ** element_t data; 待放入的元素 ** Output: ** link_t * link; 添加新元素后的链表指针 ** return: 类型:int; 为-1表示放入失败,一般是因为申请不到链点空间,为0表示正确放入 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ int add_link(link_t * link, element_t data) { node_t *p,*t; p = (node_t *)malloc(sizeof(node_t)); //申请新的结点 t = (node_t *)malloc(sizeof(node_t)); if (p==NULL||t==NULL) return -1; else if(link->head==NULL) { link->head=t; t->data=data; t->next=NULL; link->length++; return 0; } else { p=link->head; while(p->next!=NULL) p=p->next; p->next=t; t->data = data; //结点数据域赋值 t->next=NULL; link->length++; return 0; } } /******************************************************************************************* ** Function name: get_link() ** Descriptions : 查询链表 ** 查询链表中第i个元素 ** Input: ** link_t * link; 顺序表指针 ** int index; 查询位置,即第i个元素 ** Output: ** element_t * elem; 元素域指针,用来存放被查询到的元素内容, ** (注意,需要将元素全部内容拷贝到该指针所记录的空间中,即,使用memcpy()) ** return: 类型:int,返回查询是否成功,为0表示找到指定元素,为-1表示没有找到,一般是因为 ** index指示的位置超出了顺序表的范围 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ int get_link(link_t * link,int index, element_t * elem) { node_t *p; int j=1; p=link->head; if(index <= 0 || index > link->length){ return -1; } while(p->next!=NULL&&j<index) { p=p->next; j++; } if (p!=NULL&&j==index) memcpy(elem,&(p->data),sizeof(element_t)); return 0; } /******************************************************************************************* ** Function name: insert_link() ** Descriptions : 将指定元素插入到链表的指定位置之前 ** Input: ** link_t * link; 链表结构指针 ** element_t data; 待放入的元素 ** int location; 插入位置,语义是:第X个元素前,当location大于链表元素总数时,该元素 ** 将插入到表尾。 ** Output: ** link_t * link; 插入新元素后的链表结构指针 ** return: 类型:int; 为-1表示插入失败,一般是因为没有申请到空间而无法生成链点 为0表示正确插入 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ int insert_link(link_t * link, element_t data, int location) { node_t *p,*t; t=(node_t *)malloc(2*sizeof(node_t)); p=(node_t *)malloc(sizeof(node_t)); int j=1; p=link->head; while(p!=NULL&&j<location-1) { p=p->next; j++; } if(j!=location-1) { return -1; } else { t->data=data; t->next=p->next; p->next=t; link->length++; return 0; } } /******************************************************************************************* ** Function name: insert_link_by_order() ** Descriptions : 将指定元素按照学号从小到大顺序插入到链表中 ** Input: ** link_t * link; 链表指针 ** element_t data; 待放入的元素 ** Output: ** link_t * link; 插入新元素后的链表指针 ** return: 类型:int; 为-1表示插入失败,一般是因为没有申请到空间而无法生成链点, 为0表示正确插入 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ int insert_link_by_order(link_t * link, element_t data) { int i=0,j=0; node_t *p,*s,*t; t=(node_t *)malloc(sizeof(node_t)); p=(node_t *)malloc(sizeof(node_t)); s=(node_t *)malloc(sizeof(node_t)); element_t temp; for(i=1;i<link->length-1;i++) { p=link->head; for(j=0;j<link->length-i;j++) { if(p->data.stuID>p->next->data.stuID) { temp=p->data; p->data=p->next->data; p->next->data=temp; } p=p->next; } } p=link->head; if(data.stuID<=link->head->data.stuID) { t->data=data; t->next=link->head->next; link->head=t; link->length++; return 0; } else { p=link->head; while(p->next!=NULL) { if(data.stuID<=p->next->data.stuID) { // s=p->next; t->data=data; // p->next=t; // t->next=s; t->next=p->next; p->next=t; link->length++; return 0; } p=p->next; } } } /******************************************************************************************* ** Function name: delete_link() ** Descriptions : 删除链表中指定姓名作为关键字的元素 ** Input: ** link_t * link; 链表指针 ** char * name; 以该姓名为关键字的元素将被删除,其链点空间也需要被释放 ** Output: ** link_t * link; 删除指定元素后的链表指针 ** return: 类型:int; 为-1表示删除失败,一般是因为在链表中没有找到指定元素, 为0表示正确删除 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ int delete_link(link_t * link, char * name) { node_t *p,*s; int j=0,i=0; p=link->head; while(strcmp(p->data.stuName,name)!=0) { p=p->next; j++; } p=link->head; while(p->next!=NULL&&i<j-1) { p=p->next; i++; } if(p->next==NULL) return -1; s=p->next; p->next=s->next; free(s); link->length--; return 0; } /******************************************************************************************* ** Function name: delete_link_below() ** Descriptions : 删除链表中总分小于某个指定值的所有元素,本算法的特点是 ** 希望一趟能在链表中删除多个元素 ** Input: ** link_t * link; 链表指针 ** int x; 删除范围,即被删除的元素总分小于这个值 ** Output: ** link_t * link; 删除元素后的链表结构指针 ** return: 类型:void; ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ void delete_link_below(link_t * link, int x) { node_t *p,*t,*s; while(link->head->data.overall<x) { t=link->head->next; link->head=t; link->length--; } p=link->head; while(p->next!=NULL) { s=p->next; if(s->data.overall<x) { p->next=s->next; link->length--; } else { p=p->next; } } } ex2_2——扩展题 1)创建一个单链表,其数据元素为整数,从键盘输入,输入0结束(注意0不放到链表内); 2)从键盘任意输入一个整数,在单链表中查询该数,如果单链表中已经存在这个数,就调用删除函数,删除该元素所在结点,并将单链表在删除前后的数据元素依次输出到屏幕上; 如果单链表中不存在这个数,就调用插入函数,将这个数插入到单链表尾,并将单链表在插入前后的数据元素依次输出到屏幕上。 3)教材第一章习题第9题(用链表实现) ex2_3——扩展题 1)删除单链表中全部的负数 2)创建一个双向链表,按照冒泡排序的思路对这个双向链表进行排序,打印排序结果。注意,本算法在交换元素时是将链点整个交换而不是将链点中的元素值交换。 程序一: ex2_2_12——扩展题 1)创建一个单链表,其数据元素为整数,从键盘输入,输入0结束(注意0不放到链表内); 2)从键盘任意输入一个整数,在单链表中查询该数,如果单链表中已经存在这个数,就调用删除函数,删除该元素所在结点,并将单链表在删除前后的数据元素依次输出到屏幕上; 如果单链表中不存在这个数,就调用插入函数,将这个数插入到单链表尾,并将单链表在插入前后的数据元素依次输出到屏幕上。 程序二:用链表实现有序向量按序插入元素。(教材第九题) 程序三:删除单链表中的所有负数。 程序四:创建一个双向链表,按照冒泡排序的思路对这个双向链表进行排序,打印排序结果。注意,本算法在交换元素时是将链点整个交换而不是将链点中的元素值交换。 程序四:ex2_3_2流程说明: 源程序清单如下: 程序文件名为ex2_2_12.cpp,源程序: #include<stdio.h> #include<stdlib.h> //by 郑元帅 2016010901012 软件技术基础实验 UESTC //定义节点结构,定义链表结构 typedef struct node_t{ int data; struct node_t* next; }node_t; typedef struct link_t{ node_t * head; int length; }link_t; //创建链表函数 int add_link(link_t * link, int data) { node_t *p,*t; //申请新的结点 p = (node_t *)malloc(sizeof(node_t)); t = (node_t *)malloc(sizeof(node_t)); if (p==NULL||t==NULL) return -1; else if(link->head==NULL) { link->head=t; t->data=data; t->next=NULL; link->length++; return 0; } else { p=link->head; while(p->next!=NULL) p=p->next; p->next=t; t->data = data; //结点数据域赋值 t->next=NULL; link->length++; return 0; } } //删除与查找元素相同的元素函数 int delete_link(link_t * link, int del) { node_t *p,*s; //利用flag来计算一共有几个与输入元素相同的值 //便于遍历和删除 int flag=0,leng=0; //申请新的节点 p = (node_t *)malloc(sizeof(node_t)); s = (node_t *)malloc(sizeof(node_t)); int j=0,i=0,ji=0; leng=link->length; while(link->head->data==del) { flag++; link->head=link->head->next; link->length--; } //直接返回,输出链表 if(link->length==1) return 0; p=link->head; while(p->next!=NULL) { if(p->next->data==del) { flag++; } p=p->next; } //所有元素均需要删除,直接返回-2,链表为空 if(flag==leng) return -2; //没有找到需要删除的元素,返回-1,执行插入函数 else if (flag==0) return -1; for(i=0;i<flag;i++) { ji=0; j=0; p=link->head; while(p->data!=del) { p=p->next; j++; } p=link->head; while(p->next!=NULL&&ji<j-1) { p=p->next; ji++; } s=p->next; p->next=s->next; link->length--; } return 0; } //插入函数 void insert(link_t * link,int ins) { node_t *p,*s; //申请新的节点 p=(node_t*)malloc(sizeof(node_t)); s=(node_t*)malloc(sizeof(node_t)); p=link->head; while(p->next!=NULL) { p=p->next; } s->data=ins; s->next=p->next; p->next=s; link->length++; } //打印输出函数 void print(link_t * link) { node_t *p; p=(node_t *)malloc(sizeof(node_t)); int i=0; p=link->head; for(i=0;i<link->length;i++) { printf("%d\t",p->data); p=p->next; } } //主函数 int main() { link_t t; t.head=NULL; t.length=0; int x=0,search=0; int r=0,d=0; printf("请创建一个单链表(输入0结束)\n"); printf("请输入一个整数:"); scanf("%d",&x); while (x!=0) { r=add_link(&t, x); if (r==-1) { printf("链表创建失败!"); return 0; } else { printf("\n请继续输入(整数):"); scanf("%d",&x); } } printf("链表创建结束!"); printf("\nlength=%d\n",t.length); if (t.length==0) { printf("您并未创建链表,程序结束"); return 0; } else { printf("请输入一个删除或查找的整数:"); scanf("%d",&search); printf("\n原链表为\n"); print(&t); printf("\n"); d=delete_link(&t, search); if(d==-1) { printf("\n您输入的元素不在原链表中,已将其插入链表中。\n新链表为:\n"); insert(&t,search); print(&t); } else if(d==0) { printf("\n您输入的元素在原链表中,已将其删除。\n新链表为:\n"); print(&t); } else if(d==-2) { printf("\n新链表为空。"); return 0; } } } 程序文件名为ex2_2_3.cpp,源程序: //by郑元帅 2016010901012 通信与信息工程学院 指导教师:居太亮 #include<stdio.h> #include<stdlib.h> //定义节点和链表结构体 typedef struct node_t{ int data; struct node_t* next; }node_t; typedef struct link_t{ node_t * head; int length; }link_t; //模块化,子函数化 //初始化 自定义向量,包含向量长度(<0,=0,>0)判断报错 //返回值1或0,决定程序运行结束与否 //包含增序排序函数,冒泡排序法 ,可独立成子函数 //链表创建函数 int add_link(link_t * link, int data) { node_t *p,*t; p = (node_t *)malloc(sizeof(node_t)); //申请新的结点 t = (node_t *)malloc(sizeof(node_t)); if (p==NULL||t==NULL) return -1; else if(link->head==NULL) { link->head=t; t->data=data; t->next=NULL; link->length++; return 0; } else { p=link->head; while(p->next!=NULL) p=p->next; p->next=t; t->data = data; //结点数据域赋值 t->next=NULL; link->length++; return 0; } } //插入函数;包含冒泡排序法排序。 int insert_link_by_order(link_t * link, int data) { int i=0,j=0; node_t *p,*s,*t; t=(node_t *)malloc(sizeof(node_t)); p=(node_t *)malloc(sizeof(node_t)); s=(node_t *)malloc(sizeof(node_t)); int temp; for(i=1;i<link->length-1;i++) { p=link->head; for(j=0;j<link->length-i;j++) { if(p->data>p->next->data) { temp=p->data; p->data=p->next->data; p->next->data=temp; } p=p->next; } } p=link->head; if(data<=link->head->data) { t->data=link->head->data; t->next=link->head->next; link->head->data=data; link->head->next=t; link->length++; return 0; } else { p=link->head; while(p->next!=NULL) { if(data<=p->next->data) { t->data=data; t->next=p->next; p->next=t; link->length++; return 0; } p=p->next; } //单独处理最后一个元素 if(data>p->data) { t->data=data; t->next=p->next; p->next=t; link->length++; return 0; } } } // 输出函数 void print(link_t * link) { node_t *p; p=(node_t *)malloc(sizeof(node_t)); int i=0; p=link->head; for(i=0;i<link->length;i++) { printf("%d\t",p->data); p=p->next; } } //主函数,包含错误判断 ,调用子函数 int main() { link_t t; t.head=NULL; t.length=0; int x=0,search=0; int r=0,d=0; printf("1、请创建一个单链表(输入0结束)\n"); printf("请输入一个整数:"); scanf("%d",&x); while (x!=0) { r=add_link(&t, x); if (r==-1) { printf("链表创建失败!"); return 0; } else { printf("\n请继续输入(整数):"); scanf("%d",&x); } } printf("链表创建结束!"); printf("\nlength=%d\n",t.length); printf("\n请输入插入元素(数字):"); scanf("%d",&x); insert_link_by_order(&t,x); printf("\n插入元素后的向量:\n"); print(&t); } 程序文件名为ex2_3_1.cpp,源程序: #include<stdio.h> #include<stdlib.h> //定义节点、链表结构体 typedef struct node_t{ int data; struct node_t* next; }node_t; typedef struct link_t{ node_t * head; int length; }link_t; //链表创建函数 int add_link(link_t * link, int data) { node_t *p,*t; p = (node_t *)malloc(sizeof(node_t)); //申请新的结点 t = (node_t *)malloc(sizeof(node_t)); if (p==NULL||t==NULL) return -1; else if(link->head==NULL) { link->head=t; t->data=data; t->next=NULL; link->length++; return 0; } else { p=link->head; while(p->next!=NULL) p=p->next; p->next=t; t->data = data; //结点数据域赋值 t->next=NULL; link->length++; return 0; } } //删除负数函数 int delete_link(link_t * link) { node_t *p,*s; int flag=0,leng=0,flagf=0; p = (node_t *)malloc(sizeof(node_t)); s = (node_t *)malloc(sizeof(node_t)); int j=0,i=0,ji=0; leng=link->length; while(link->head->data<0) { flag++; flagf++; link->head=link->head->next; link->length--; if(link->length==0) return -1;//链表已空 } if(link->length==1) return 0; p=link->head; while(p->next!=NULL) { if(p->next->data<0) { flag++; } p=p->next; } if(flag==leng||link->length==0) return -1;//链表已空 else if (flag==0) return -2;//原链表没有负数 for(i=0;i<flag-flagf;i++) { ji=0; j=0; p=link->head; while(p->data>=0) { p=p->next; j++; } p=link->head; while(p->next!=NULL&&ji<j-1) { p=p->next; ji++; } //移动到需要删除的元素前面 s=p->next; p->next=s->next; link->length--; } return 0;//删除成功 } //打印输出函数 void print(link_t * link) { node_t *p; p=(node_t *)malloc(sizeof(node_t)); int i=0; p=link->head; for(i=0;i<link->length;i++) { printf("%d\t",p->data); p=p->next; } } //主函数 int main() { link_t t; t.head=NULL; t.length=0; int x=0,r=0,f=0; printf("请创建一个单链表\n"); printf("请输入一个整数:"); scanf("%d",&x); while (x!=0) { r=add_link(&t, x); if (r==-1) { printf("链表创建失败!"); return 0; } else { printf("\n请继续输入(整数):"); scanf("%d",&x); } } printf("链表创建结束!"); printf("\nlength=%d\n",t.length); if (t.length==0) { printf("您并未创建链表,程序结束"); return 0; } else { f=delete_link(&t); if (f==-1) { printf("链表已空,结束"); return 0; } else if (f==-2) { printf("链表中无负数"); return 0; } else { printf("程序将删除单链表中的负数,新链表为:\n"); print(&t); } } } 程序文件名为ex2_3_2.cpp,源程序: #include <stdio.h> #include<stdlib.h> #include <string.h> //定义链表结构体 typedef struct link_t { int data; struct link_t *prior; struct link_t *next; }link_t; //排序函数;冒泡排序法;交换p与pr(p前) void sort(link_t *head) { link_t *p = head->next; link_t *tail = NULL; link_t *pr=head; link_t *t=NULL; while(head->next!=tail) { p=head->next; pr=head; while(p->next!=tail) { if((p->data)>(p->next->data)) { pr->next=p->next; t=p->next->next; p->next->next=p; p->next=t; p=pr->next; //p回退一个节点 } p=p->next; //p再前进一个节点 pr=pr->next; } tail=p; } } //打印排序后结果 void print_list(link_t *head) { link_t *p = head->next; while(p != NULL) { printf("%d\t", p->data); p = p->next; } } //主函数;包含创建函数 int main() { int i=0,x=0; link_t *head = (link_t *)malloc(sizeof(link_t)); link_t *p = NULL; head->prior = head->next = NULL; printf("请输入双向链表元素(整数):\n"); scanf("%d",&x); if(x==0) { printf("链表为空,结束"); return 0; } else while(x!=0) { p = (link_t *)malloc(sizeof(link_t)); p->data = x; p->next = head->next; if(head->next != NULL) head->next->prior = p; head->next = p; p->prior = head; printf("请继续输入:\n"); scanf("%d",&x); } printf("链表创建结束。"); printf("\n链表序列为:\n "); print_list(head); sort(head); printf("\n排序后链表序列为:\n "); print_list(head); } ex3_1:链栈——基本题 1)链栈结点类型定义为: typedef struct node { int data; struct node *next; }node_type; 2)编写进栈函数push 3)编写出栈函数pop 4)编写main函数,首先建立一空链栈; 调用进栈函数,将从键盘输入的数据元素逐个进栈,输入0结束;显示进栈后的数据元素; 调用两次出栈函数,显示出栈后的数据元素。 ex3_2:循环队列——基本题 1)顺序循环队列类型定义为: #define N 20 typedef struct { int data[N]; int front, rear; }queue_type; 2)编写循环队列出队函数dequeue 3)编写循环队列入队函数enqueue 4)编写函数:void aa(queue_type *q); 其功能为,调用出队函数把队列q中的元素一一出队,如果是负数直接抛弃;如果是正数,则调用入队函数,插入到q的队尾。 5)编写main函数,首先建立一个队列,其中的数据元素为:{2, 3, -4, 6, -5, 8, -9, 7, -10, 20};然后调用aa函数,并将aa函数调用前后队列的数据元素分别输出到屏幕上。 Ex3_1 程序流程说明: 建立链栈 ——> 建立入栈函数 ——> 建立出栈函数 ——> 编写输出函数 程序文件名为ex3_1.cpp,源程序清单如下: #include<stdio.h> #include<stdlib.h> typedef struct node { int data; struct node *next; }node_type; void init(node **top) { (*top)->next=NULL; } void push(node **top,int x) { node *p; p=(node*)malloc(sizeof(node)); p->data=x; p->next=(*top); (*top)=p; } void pop(node **top) { node *p; int x; if((*top)==NULL) { printf("栈已空。"); return ; } x=(*top)->data; p=(*top); (*top)=(*top)->next; free(p); return ; } void print(node **top) { node *p=(node *)malloc(sizeof(node)); p=(*top); while(p->next!=NULL) { printf("%d\t",p->data); p=p->next; } } int main() { int x=0,length=0; node *top = (node *)malloc(sizeof(node)); init(&top); printf("请建立链栈(输入0结束):\n"); scanf("%d",&x); while(x!=0) { push(&top,x); printf("请继续输入入栈元素:\n"); scanf("%d",&x); length++; } //printf("%d",length); printf("链栈建立完成。\t"); printf("\n目前栈内元素为:\n"); print(&top); printf("\n目前栈内元素个数为:"); printf("%d\n",length); if(length>2) { pop(&top); pop(&top); printf("\n调用两次出栈函数后栈内的数据元素为:\n"); print(&top); } else if(length==2) { pop(&top); pop(&top); printf("\n调用两次出栈函数后栈内的数据元素为空\n"); } else if(length==1) { pop(&top); printf("\n调用一次出栈函数后栈内的数据元素为空\n"); print(&top); } else { printf("栈为空!"); return 0; } } Ex3_2 1. 程序流程说明: 建立队列 ——> 调用aa函数 ——> 一一出队 ——> 判断正负 ——> 负数抛弃,正数入队尾 ——> 输出原队列和新队列 2.程序文件名为ex3_2.cpp,源程序清单如下: #include<stdio.h> #include<stdlib.h> #include<string.h> #define N 20 typedef struct { int data[N]; int front,rear; }queue; //初始化队列 void init(queue *q) { q->front=0; q->rear=0; } //循环队列入队函数 int enqueue(queue *q,int x) { if((((q->rear)+1)%N)==q->front) return 0; else { q->rear=(q->rear+1)%N; q->data[q->rear]=x; return 1; } } //循环队列出队函数 int dequeue(queue *q) { if(q->rear==q->front) return -1; else { q->front=(q->front+1)%N; return (q->data[q->front]); } } //aa函数:一一出队,负数抛弃,正数入队 void aa(queue *q) { int t=0; int flag=q->rear; for(;flag>0;flag--) { t=dequeue(q); if(t<0) continue; else if(t>0) enqueue(q,t); } } //主函数 int main() { queue t; int leng=0,temp=0; int i=0; init(&t); int a[20]={2,3,-4,6,-5,8,-9,7,-10,20}; while (a[leng]!=0) { leng++; } //printf("leng=%d\n",leng); for (i=0;i<leng;i++) { temp=a[i]; enqueue(&t,temp); } //printf("t.rear=%d\n",t.rear); for (i=1;i<leng+1;i++) { printf("%d\t",t.data[i]); } aa(&t); printf("\n"); for (i=t.rear;t.rear>t.front;t.rear--) { printf("%d\t",t.data[t.rear]); } } ex3_3:教材第一章习题12题——扩展题 1)两个栈共用一个数组空间,它们的栈底分别在数组两端,栈顶相向而行。编写入栈和出栈函数,实现两个栈元素分别的(但共用)入栈和出栈。 2)main中函数完成以下测试: a、能否在共用空间上实现两个独立的栈:即能否向两个栈分别输入元素;能否分别从两个栈取出元素,每个栈取出的元素的顺序符合各自栈的特点 b、能否在共用空间用满时,及时制止新的入栈行为。 例如: 假设数组大小为6,main函数实现以下动作,向栈1接连入栈4个元素后,向栈2入栈2个元素致栈满,再向栈2输入一个元素,将报错。接着从栈1出栈1个元素,再向栈2入栈,就会成功。最后,两个栈分别出空,观察输出顺序是否满足栈的特点。 ex3_4:教材第一章习题13题——扩展题 1)实现一种扩展的循环队列,使得全部的数组空间都能使用,基本思路是当传统循环队列放满时:即 (rear+1)%MAXNUM ==front 为真 时,可以再入队一个元素,接着rear = (rear+1)%MAXNUM后就会与front相等,此时将另外一个变量flag设置为1,表示此时的rear==front不是为空,而是满。否则flag为0时,如果出现rear==front,则表示队列为空。 2)main()函数实现以下测试: a、能否实现全部“装满”,即装入元素个数为MAXNUM b、能否按照循环队列那样绕着存放空间循环存放。 c、能否在装满后,拒绝再装。 d、能否在装满后,不会变成“空”的——即可以还可正常出队。 e、能否在全部出空后,不会变成“满”的——即可还可正常入队。 例如: 假设循环队列最大空间为5,main()函数实现以下动作,接连成功入队5个元素,入队第6个元素时,报错。接着出队3个元素,入队3个元素,均成功。再入队1个,报错。继续连续成功出队6个元素,出队第7个时报错。最后,再成功入队2个元素。 ex3-5——扩展题(选做) 利用栈实现算术四则运算,即录入一个包含加减乘除运算的多项式,计算出结果。暂不考虑“括号”。 本题算法难点在如何利用栈,驱动运算过程。 本题程序难点在从输入的一个形如“3+4×16-4/3”的字符串中依次提取出各个数字和运算符——可利用CString。 ex3-6——教材(第5版例5)扩展题(选做) 计算并输出二项展开式(a+b)n的各项系数,即求一个杨辉三角形的最下面一层所有元素。 本题算法难点在利用杨辉三角形计算原理,不断利用队列在上一层元素的基础上,求出下一层元素。 程序文件名为ex3_3.cpp,源程序清单如下: #include<stdio.h> //by 郑元帅 2016010901012 指导教师:居太亮 struct STACK { int stack[1000]; int top0,top1; }stack_int; int m=0; //初始化函数 void init(STACK *p,int m) { p->top0=0; p->top1=m-1; } //入栈函数 void push(STACK *p,int i,int data) { //printf("%d",p->top0); //printf("%d",p->top1); if (i==0) { if(p->top0<0||p->top0>p->top1) { printf("\nerror!pre栈已满,已无法入栈!\n"); } else { //printf("attention place"); p->stack[p->top0]=data; p->top0++; } } else if (i==1) { if(p->top1<p->top0) { printf("error,pre栈满!"); } else { p->stack[p->top1]=data; p->top1--; } } } //出栈函数 int pop(STACK *p,int i,int m) { if (i==0) { if(p->top0<0) { printf("栈空!\n"); return NULL; } else { p->top0--; if(p->top0<0) { printf("栈空!\n"); return NULL; } else return p->stack[p->top0]; } } else if (i==1) { //printf("m=%d\n",m); //printf("top1=%d\n",p->top1); if(p->top1>m-1) { printf("栈空!\n"); return NULL; } else { p->top1++; // if(p->top1==-1) // p->top1=0; if(p->top1>m-1) { printf("栈空!\n"); return NULL; } else return p->stack[p->top1]; } } else { return NULL; } } //主函数 int main() { STACK stack_int; int x=0,i=0,m=0,data=0,a=0,flag=0,t=0; printf("请输入一维数组的长度(>=0的自然数):"); scanf("%d",&m); init(&stack_int,m); if (m<0) { printf("长度不符合要求"); return 0; } else { printf("数组长度初始化成功,length=%d\n",m); printf("\n请输入需要进行的操作:\n"); printf("1、向栈1入栈。\n2、向栈2入栈。\n3、栈1出栈。\n4、栈2出栈。\n5、退出\n"); scanf("%d",&flag); while(1) { if(flag==1) { printf("请输入向栈1入栈的元素:\n"); scanf("%d",&data); push(&stack_int,0,data); //printf("入栈成功!"); } else if(flag==2) { printf("请输入向栈2入栈的元素:\n"); scanf("%d",&data); push(&stack_int,1,data); //printf("入栈成功!"); } else if(flag==3) { a=pop(&stack_int,0,m); printf("出栈元素为:\n%d",a); } else if(flag==4) { a=pop(&stack_int,1,m); printf("出栈元素为:\n%d",a); } else { printf("程序已成功退出。"); return 0; } printf("\n请输入需要进行的操作:\n"); printf("1、向栈1入栈。\n2、向栈2入栈。\n3、栈1出栈。\n4、栈2出栈。\n5、退出\n"); scanf("%d",&flag); } } } Ex3_4 1. 程序流程说明: 初始化queue长度 ——> 1、入队函数 ——> 2、出队函数 ——> 3、循环执行操作 ——> 退出 2.程序文件名为ex3_4.cpp,源程序清单如下: #include <stdio.h> #define M 5 //by 郑元帅 软循环队列算法 2016010901012 指导教师:居太亮 //这里tag=0表示队列为空,tag=1表示队列已满(均有操作提示) //增加了tag=3的语句,目的:使得在队列未满或者未空状态下能够自由进行入队出队操作 //使之与相关判断兼容,提高容错性。 int main() { int queue[M]; int tag = 0; int flag=0;//用户输入指令 int front = 0; int rear=0; int x=0;//入队列元素 int l=0; printf("请选择要执行的操作:\n1:入队\n2:出队\n3:退出\n"); scanf("%d",&flag); //诸多判断,提高容错性,给用户详细的操作说明。 if(flag==2) { printf("error:队列为空,不可执行出队操作"); return 0; } else if(flag<1&flag>3) { printf("error:输入指令错误"); return 0; } else if(flag==3) { printf("\n已退出"); return 0; } else { while(flag!=3) { if(flag==1) { if(tag!=1) { printf("请输入入队数值:"); scanf("%d",&x); queue[rear%M]=x; rear=(rear+1)%M;//队尾指针增加 tag=3;//使得在队列未满或者未空状态下能够自由进行入队出队操作 l++;//长度计算 if(rear == front) { tag = 1; //printf("队列已满\n"); } } } else if(flag == 2) { if(tag!=0) { printf("出队数值为:%d\n",queue[front]); front=(front+1)%M; if(rear == front) { tag = 0; //printf("队列已空\n"); } } } printf("请选择要执行的操作:\n1:入队\n2:出队\n3:退出\n"); scanf("%d",&flag); if(tag==0&flag==2) { printf("error:队列已空,不可执行出队操作\n"); tag=3; printf("请选择要执行的操作:\n1:入队\n2:出队\n3:退出\n"); scanf("%d",&flag); // return 0; } else if(tag==1&flag==1) { printf("error:队列已满,不可执行入队操作\n"); tag=3; printf("请选择要执行的操作:\n1:入队\n2:出队\n3:退出\n"); scanf("%d",&flag); // return 0; } else if(flag>3||flag<1) { printf("error:输入指令错误"); // return 0; } else if(flag==3) { printf("已退出"); return 0; } else continue; } } return 0; } Ex3_5 1. 程序流程说明: 定义数字入栈出栈,符号入栈出栈函数 ——> 定义输入函数 ——> 定义加减乘除入栈顺序函数 ——> 定义中缀和后缀转换函数 ——> 定义计算函数 ——> 结束 2.程序文件名为ex3_5.cpp,源程序清单如下: #include<stdio.h> #include<string.h> #include<ctype.h> #include<stdlib.h> //by 郑元帅 UESTC 软件技术实验 指导教师:居太亮 //程序利用中缀和后缀转换和后缀的四则运算实现。 //定义栈的结构体 #define max 100 typedef struct stack_t{ int num=0; char ope='='; int isnum=0; }stack; //定义中缀和后缀栈 stack median[max]; stack after[max]; //定义数字和符号的存储数组 double stacknum[max]; char stackope[max]; int numtop=0; int opetop=0; //定义符号入栈函数 void pushope(char ope) { stackope[opetop++]=ope; } //定义符号入栈函数,返回字符型变量 char popope() { return stackope[--opetop]; } //定义数字入栈函数 void pushnum(double data) { stacknum[numtop++]=data; } //定义数字出栈函数,返回double型变量 double popnum() { return stacknum[--numtop]; } //定义输入函数 int get() { //定义输入存储字符数组 char input[max]; printf("请输入四则运算式"); gets(input); // if(input[0]=='c') // return 0; //num为多位数变量 int num=0; for (int i=0,j=0;i<max;i++) { //获得多位数 if(isdigit(input[i])) { num=num*10+input[i]-'0'; } else { if(input[i]=='=') { if(input[i-1]!='=') { //将num的数值放入中缀栈中,并将中缀设置为1 median[j].isnum =1; median[j++].num=num; //num置零 num=0; } //否则,将中缀设置为0,未结束 //将中缀符号设置为= median[j].isnum=0; median[j++].ope='='; break; } //判断括号(不要求),如果是左括号,则在中缀栈中放入左括号,并将符号置零 else if(input[i]=='(') { median[j].isnum=0; median[j++].ope='('; } //判断右括号,如果是右括号,则在中缀栈中放入右括号,并将符号置零 else if(input[i]==')'&&input[i-1]==')') { median[j].isnum=0; median[j++].ope=')'; } //其他符号,将中缀符号置1,将数字放入中缀栈 中,将符号放入中缀站中。 else { median[j].isnum=1; median[j++].num=num; num=0; median[j].isnum=0; median[j++].ope=input[i]; } } } //输出查看中缀栈内元素 for(int i=0;i<max;++i) { if(!median[i].isnum&&median[i].ope=='=') { printf("%c\n",'='); break; } //中缀符号为1时,输出数字,中缀符号为0时,输出符号 else if (median[i].isnum) { printf("%d",median[i].num); } else { printf("%c",median[i].ope); } } return 1; } //声明子函数 void isadd(int *j); void issub(int *j); void ismulti(); void isdiv(); void isleft(); void isright(int *j); void isequal(int *j); //中缀与后缀转换函数 void translate() { int i=0; int j=0; for(i=0,j=0;i<max;++i) { //判断数字,置入后缀栈中 if(median[i].isnum) { after[j].isnum=1; after[j++].num=median[i].num; } else { switch(median[i].ope) { case '(': isleft(); break; case ')': isright(&j); break; case '+': isadd(&j); break; case '-': issub(&j); break; case '*': ismulti(); break; case '/': isdiv(); break; case '=': isequal(&j); return; } } } } //左边,直接入栈 void isleft() { pushope('('); } //右边,出栈,后缀符号入栈,置零 void isright(int *j) { char ope; while(opetop>0) { ope=popope(); if(ope=='(') return ; else { after[(*j)].isnum=0; after[(*j)++].ope=ope; } } } //加法,出栈,后缀符号入栈 void isadd(int *j) { char ope; while(opetop>0) { ope=popope(); if(ope==')') { pushope(ope); break; } else { after[(*j)].isnum=0; after[(*j)++].ope=ope; } } pushope('+'); } //减法,出栈,后缀符号入栈 void issub(int *j) { char ope; while(opetop>0) { ope=popope(); if(ope=='(') { pushope(ope); break; } else { after[(*j)].isnum=0; after[(*j)++].ope=ope; } } pushope('-'); } //乘法子函数,直接入栈 void ismulti() { pushope('*'); } //除法子函数,直接入栈 void isdiv() { pushope('/'); } //等号,后缀入栈,符号置零 void isequal(int *j) { char ope; while(opetop>0) { ope=popope(); after[(*j)].isnum=0; after[(*j)++].ope=ope; } after[(*j)].isnum=0; after[(*j)++].ope='='; } //计算函数 double calculate() { int i=0; for(i=0;i<max;++i) { //输出后缀表达式 if(!after[i].isnum&&after[i].ope=='=') { printf("%c\n",'='); break; } else if(after[i].isnum) { printf("%d",after[i].num); } else { printf("%c",after[i].ope); } } for(i=0;i<max;++i) { if(!after[i].isnum&&after[i].ope=='=') { return popnum(); } else if(after[i].isnum) { pushnum((double)(after[i].num)); } else { //非=,分别出栈两个,利用后缀中的符号判断运算,将两个数值运算,并将结果入栈 double temp=0.0; double rear=popnum(); double front=popnum(); switch(after[i].ope) { case '+': temp=front+rear; pushnum(temp); break; case '-': temp=front-rear; pushnum(temp); break; case '*': temp=front*rear; pushnum(temp); break; case '/': temp=front/rear; pushnum(temp); break; } } } return 0; } //主函数 int main() { while(1) { if(get()) { //调用转换和运算函数 translate(); double result=calculate(); printf("result is %lf\n",result); } else break; } return 0; } Ex3_6 1. 程序流程说明: 自定义二项式指数 ——> 将各项系数初始化为1 ——> 入基本元素到队列指定位置 ——> 将第m行的非1元素利用规律进行计算 ——> 将计算结果入队列相应位置 ——> 下一行利用上一行元素出队列后进行操作 ——> 以此类推 ——> 将各项系数补齐 ——> 输出并结束 2.程序文件名为ex3_6.cpp,源程序清单如下: #include<stdio.h> #include<stdlib.h> #include<string.h> #define N 100 typedef struct { int data[N]; int front,rear,cir; }queue; //初始化队列 void init(queue *q) { q->front=0; q->rear=0; q->cir=0; } //入队操作 int enqueue(queue *q,int x) { q->data[q->rear]=x; q->rear=(q->rear+1)%N; return 1; } //出队操作 int dequeue(queue *q) { int temp=0; temp=q->data[q->cir]; q->front=(q->front+1)%N; q->cir=(q->cir+1)%N; return (temp); } //主函数 int main() { queue t; int n=0,x1=0,x2=0; int i=0,j=0; int a=0,u=0; int p=0,k=0; int output=0; int number=0; init(&t); printf("请输入(a+b)^n中的n:"); scanf("%d",&n); printf("二项展开式的各项系数为:\n"); for(i=0;i<n;i++) { enqueue(&t,1); } t.rear=0; enqueue(&t,1); enqueue(&t,1); enqueue(&t,1); enqueue(&t,1); // printf("rear=%d\n",t.rear); for(int m=3;m<=n;m++) { p=m*(m-1)/2; for(k=1;k<=m-2;k++) { for(j=0;j<=p+k-m;j++) { x1=dequeue(&t); } x2=dequeue(&t); //printf("x1=%d\t",x1); // printf("x2=%d\n",x1); //printf("front=%d\n",t.front); t.cir=0; t.data[p+k]=x1+x2; enqueue(&t,t.data[p+k]); //printf("t-data[%d]=%d\n",p+k,t.data[p+k]); } if(t.rear==m*(m+1)/2-1) { enqueue(&t,1); enqueue(&t,1); } } // printf("t-data[%d]=%d\n",p+k,t.data[6]); t.front=0; for(i=0;i<n*(n-1)/2;i++) { output=dequeue(&t); } //printf("front=%d\n",t.front); printf("\n\n___________________________________\n\n\n"); for(number=0;number<n;number++) { output=dequeue(&t); printf("%d\t",output); } printf("\n\n___________________________________\n\n\n"); } 程序流程说明: 初始化二叉树 ——> 建立插入函数,构造二叉排序树 ——> 中序遍历二叉树 ——> 先序遍历二叉树 ——> 后序遍历二叉树 ——> 编写二叉树搜索函数,查找指定数据元素 ——> 释放存储空间 程序文件名为tree.cpp,源程序清单如下: /*******************************Copyright (c)********************************************* ** University of Electronic Science and Technology of China ** School of Communication and Information Engineering ** http://www.uestc.edu.cn ** **--------------------------- File Info --------------------------------------------------- ** File name: tree.cpp ** Last modified Date: 2012-12-19 ** Last Version: 1.0 ** Descriptions: 各种二叉树操作,二叉树结构的定义在mystruct.h中, ** 函数中使用的与界面显示有关接口的说明在ui.h ** 本文件基于C语言风格 **------------------------------------------------------------------------------------------ ** Created by: Duan Jingshan ** Created date: 2012-12-19 **------------------------------------------------------------------------------------------ ** Modified by: ** Modified date: ** Version: ** Descriptions: ** *******************************************************************************************/ #include "stdafx.h" #include "mystruct.h" #include "ui.h" /******************************************************************************************* ** Function name: init_tree() ** Descriptions : 初始化二叉树 ** 二叉树的是非线性结构,大多数情况下采用链接存储,采用动态申请内存的方式 ** 在需要的时候为链点申请空间。二叉树结构中最重要的是根节点指针,因此在初 ** 始化时,除了要申请二叉树结构空间外,还应将其中的根节点指针设置为空 ** Input: NONE ** Output: NONE ** return: 类型:tree_t *,返回链表的结构指针 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ tree_t * init_tree() { tree_t * t = (tree_t *)malloc(sizeof(tree_t));; t->num=0; t->root=NULL; return t; } /******************************************************************************************* ** Function name: free_tree() ** Descriptions : 释放二叉树结构 ** 当程序结束时会通过本函数来释放二叉树空间,如果二叉树中有多个元素,则需要 ** 逐个将元素的空间予以释放。 ** Input: tree_t * t; 链表结构指针 ** Output: NONE ** return: 类型:void ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ void free_tree(tree_t * tree) { if(tree == NULL){ return; } free_tree_nodes(tree->root); free(tree); return; } /******************************************************************************************* ** Function name: free_tree_nodes() ** Descriptions : 释放二叉树的所有链点 ** 当程序结束时会通过本函数来释放二叉树空间,如果二叉树中有多个元素,则需要逐个将 ** 元素的空间予以释放,由于二叉树是非线性结构,可以考虑采用后根遍历递归框架释放 ** 各个链点,采用后根的原因是根节点的空间不能早于子树节点空间释放,否则无法继续 ** 继续遍历链表 ** Input: tnode_t * root; 二叉树根结点指针 ** Output: NONE ** return: 类型:void ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ void free_tree_nodes(tnode_t * root) { if(root == NULL){ return; } if(root->Lchild != NULL) free_tree_nodes(root->Lchild); if(root->Rchild != NULL) free_tree_nodes(root->Rchild); free(root); return; } /******************************************************************************************* ** Function name: insert_BS_tree() ** Descriptions : 向二叉排序树插入一个元素,以元素中的数据项——总分作为排序码 ** Input: ** tree_t * tree; 二叉树指针 ** element data; 新元素 ** Output: NONE ** return: 类型:int,0,表示成功插入;-1,表示插入失败,一般是因为没有足够的内存 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ int insert_BS_tree(tree_t * tree, element_t data) { tnode_t *dr=(tnode_t *)malloc(sizeof(tnode_t)); tnode_t *pr=(tnode_t *)malloc(sizeof(tnode_t)); //tnode_t *pr_l=(tnode_t *)malloc(sizeof(tnode_t)); //tnode_t *pr_r=(tnode_t *)malloc(sizeof(tnode_t)); //pr->Lchild=NULL; //pr->Rchild=NULL; if(tree->root==NULL) { dr->data=data; dr->Lchild=NULL; dr->Rchild=NULL; tree->root=dr; tree->num++; } else { dr=tree->root; while(dr!=NULL) { if(data.overall<dr->data.overall) { if(dr->Lchild==NULL) { pr->data=data; pr->Lchild=NULL; pr->Rchild=NULL; dr->Lchild=pr; tree->num++; break; } else dr=dr->Lchild; } else { // dr=dr->Rchild; if(dr->Rchild==NULL) { pr->data=data; pr->Lchild=NULL; pr->Rchild=NULL; dr->Rchild=pr; tree->num++; break; } else dr=dr->Rchild; } } //if(data.overall<pr->data.overall) // pr->Lchild->data=data; //else // pr->Rchild->data=data; //if(data.overall<dr->data.overall) //dr->Lchild->data=data; //else // dr->Rchild->data=data; } return 0; } /******************************************************************************************* ** Function name: inorder_tree() ** Descriptions : 中序(根)遍历一棵二叉树, ** 在访问节点内容时,调用ui.h中的ShowElement()来将元素内容显示在窗口内 ** 以供检查 ** Input: ** tnode_t * root; 二叉树指针 ** Output: NONE ** ** return: 类型:void ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ void inorder_tree(tnode_t * root) { if(root==NULL) return; else { if(root->Lchild!=NULL) { inorder_tree(root->Lchild); } ShowElement(root->data); if(root->Rchild!=NULL) { inorder_tree(root->Rchild); } } } /******************************************************************************************* ** Function name: preorder_tree() ** Descriptions : 先序(根)遍历一棵二叉树, ** 在访问节点内容时,调用ui.h中的ShowElement()来将元素内容显示在窗口内 ** 以供检查 ** Input: ** tnode_t * root; 二叉树指针 ** Output: NONE ** ** return: 类型:void ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ void preorder_tree(tnode_t * root) { if(root==NULL) return; else { ShowElement(root->data); if(root->Lchild!=NULL) { preorder_tree(root->Lchild); } if(root->Rchild!=NULL) { preorder_tree(root->Rchild); } } } /******************************************************************************************* ** Function name: postorder_tree() ** Descriptions : 后序(根)遍历一棵二叉树, ** 在访问节点内容时,调用ui.h中的ShowElement()来将元素内容显示在窗口内 ** 以供检查 ** Input: ** tnode_t * root; 二叉树指针 ** Output: NONE ** ** return: 类型:void ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ void postorder_tree(tnode_t * root) { if(root==NULL) return; else { if(root->Lchild!=NULL) { postorder_tree(root->Lchild); } if(root->Rchild!=NULL) { postorder_tree(root->Rchild); } ShowElement(root->data); } return ; } /******************************************************************************************* ** Function name: get_element_tree() ** Descriptions : 在二叉树中,查询指定学号的元素,获得该元素的链点指针,以备进一步访问所需 ** 查询算法需要对二叉树进行遍历,可采用先序(根)遍历算法的框架, ** Input: ** tnode_t * root; 二叉树指针 ** double stuID; 学号 ** Output: NONE ** ** return: 类型:tnode_t *; 返回具有指定学号的链点指针,如果没找到则返回值为NULL ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ tnode_t * get_element_tree(tnode_t * root, double stuID) { tnode_t * ret = NULL; tnode_t * retr = NULL; tnode_t *p=NULL; p=root; // while(p!=NULL) // { // if(stuID==p->data.stuID) // { // return p; // } // else if(stuID<p->data.stuID){ // p = p->Lchild; // } // else{ // p = p->Rchild; // } // } // if(p == NULL) // { // return NULL; // } if(p==NULL) return NULL; else { if(p->data.stuID==stuID) return root; if(p->Lchild!=NULL) { tnode_t * ret = NULL; ret=p->Lchild; if(ret->data.stuID==stuID) return ret; else get_element_tree(ret, stuID); } if(p->Rchild!=NULL) { tnode_t * retr = NULL; retr=p->Rchild; if(retr->data.stuID==stuID) return retr; else get_element_tree(retr, stuID); } } } 六、 实验内容: ex4_2——扩展题 1)实现二叉排序树的插入函数 2)main函数中,输入一组无序数,调用二叉排序树插入算法,将元素放入二叉树中 3)中序遍历这颗二叉树,得到排序顺序。 ex4-3——扩展题 2) 编写函数求一颗二叉树的深度 2)求一颗二叉排序树的排序的反序结果,即将二叉排序树每个节点的左右子树交换,然后中序遍历之。 ex4-4——扩展题(选做) 1)输入一组数(权值),编写建立哈夫曼树的函数 2)以先序遍历为框架,输出每个权值对应的二进制编码 Ex4_2 程序流程说明: 二叉树初始化 ——> 插入构造二叉树 ——> 中序遍历 程序文件名为ex4_2.cpp,源程序清单如下: #include<stdio.h> #include<stdlib.h> //ex4_2——扩展题 //1)实现二叉排序树的插入函数 //2)main函数中,输入一组无序数,调用二叉排序树插入算法,将元素放入二叉树中 //3)中序遍历这颗二叉树,得到排序顺序。 typedef struct tnode_t{ int data; struct tnode_t * Lchild; struct tnode_t * Rchild; }tnode_t; typedef struct tree_t{ tnode_t * root; int num; }tree_t; //初始化二叉树 void init_tree(tree_t *t) { t->num=0; t->root=NULL; } //二叉排序树插入函数 int insert_BS_tree(tree_t * tree, int data) { tnode_t *dr=(tnode_t *)malloc(sizeof(tnode_t)); tnode_t *pr=(tnode_t *)malloc(sizeof(tnode_t)); if(tree->root==NULL) { dr->data=data; dr->Lchild=NULL; dr->Rchild=NULL; tree->root=dr; tree->num++; } else { dr=tree->root; while(dr!=NULL) { if(data<dr->data) { if(dr->Lchild==NULL) { pr->data=data; pr->Lchild=NULL; pr->Rchild=NULL; dr->Lchild=pr; tree->num++; break; } else dr=dr->Lchild; } else { if(dr->Rchild==NULL) { pr->data=data; pr->Lchild=NULL; pr->Rchild=NULL; dr->Rchild=pr; tree->num++; break; } else dr=dr->Rchild; } } } return 0; } // 中序(根)遍历一棵二叉树, void inorder_tree(tnode_t * root) { if(root==NULL) return; else { if(root->Lchild!=NULL) { inorder_tree(root->Lchild); } printf("%d\t",root->data); if(root->Rchild!=NULL) { inorder_tree(root->Rchild); } } } //main函数中,输入一组无序数,调用二叉排序树插入算法,将元素放入二叉树中 int main() { tree_t t; int x[100]; int i=0,j=0; int length=0; int data=0; init_tree(&t); printf("请输入无序数的长度\n"); scanf("%d",&length); printf("请输入一组无序数:\n"); for (i=0;i<length;i++) { scanf("%d",&x[i]); data=x[i]; insert_BS_tree(&t,data); } inorder_tree(t.root); } Ex4_3 1. 程序流程说明: 初始化二叉树 ——> 创建二叉树 ——> 求深度 ——> 反序 ——> 中序遍历 2.程序文件名为ex4_3.cpp,源程序清单如下: #include<stdio.h> #include<stdlib.h> //ex4-3——扩展题 //1)编写函数求一颗二叉树的深度 //2)求一颗二叉排序树的排序的反序结果,即将二叉排序树每个节点的左右子树交换,然后中序遍历之。 typedef struct tnode_t{ int data; struct tnode_t * Lchild; struct tnode_t * Rchild; }tnode_t; typedef struct tree_t{ tnode_t * root; int num; }tree_t; //初始化二叉树 void init_tree(tree_t *t) { t->num=0; t->root=NULL; } //二叉排序树插入函数 int insert_BS_tree(tree_t * tree, int data) { tnode_t *dr=(tnode_t *)malloc(sizeof(tnode_t)); tnode_t *pr=(tnode_t *)malloc(sizeof(tnode_t)); if(tree->root==NULL) { dr->data=data; dr->Lchild=NULL; dr->Rchild=NULL; tree->root=dr; tree->num++; } else { dr=tree->root; while(dr!=NULL) { if(data<dr->data) { if(dr->Lchild==NULL) { pr->data=data; pr->Lchild=NULL; pr->Rchild=NULL; dr->Lchild=pr; tree->num++; break; } else dr=dr->Lchild; } else { if(dr->Rchild==NULL) { pr->data=data; pr->Lchild=NULL; pr->Rchild=NULL; dr->Rchild=pr; tree->num++; break; } else dr=dr->Rchild; } } } return 0; } int insert_BS_tree_inverse(tree_t * tree, int data) { tnode_t *dr=(tnode_t *)malloc(sizeof(tnode_t)); tnode_t *pr=(tnode_t *)malloc(sizeof(tnode_t)); if(tree->root==NULL) { dr->data=data; dr->Lchild=NULL; dr->Rchild=NULL; tree->root=dr; tree->num++; } else { dr=tree->root; while(dr!=NULL) { if(data>dr->data) { if(dr->Lchild==NULL) { pr->data=data; pr->Lchild=NULL; pr->Rchild=NULL; dr->Lchild=pr; tree->num++; break; } else dr=dr->Lchild; } else { if(dr->Rchild==NULL) { pr->data=data; pr->Lchild=NULL; pr->Rchild=NULL; dr->Rchild=pr; tree->num++; break; } else dr=dr->Rchild; } } } return 0; } int depth(tnode_t *root) { int u=0; int v=0; if(root==NULL) return 0; u=depth(root->Lchild); v=depth(root->Rchild); if(u>v) return (u+1); else return (v+1); } void inorder_tree(tnode_t * root) { if(root==NULL) { return; } else { if(root->Lchild!=NULL) { inorder_tree(root->Lchild); } printf("%d\t",root->data); if(root->Rchild!=NULL) { inorder_tree(root->Rchild); } } } int main() { tree_t t; tree_t t_inverse; int x[100]; int i=0,j=0; int length=0; int data=0; int deepth=0; init_tree(&t); init_tree(&t_inverse); printf("请输入无序数的长度\n"); scanf("%d",&length); printf("请输入一组无序数:\n"); for (i=0;i<length;i++) { scanf("%d",&x[i]); data=x[i]; insert_BS_tree(&t,data); } printf("\n二叉排序树中序遍历结果:\n"); inorder_tree(t.root); deepth=depth(t.root); printf("\n二叉树的深度为%d.\n",deepth); for(i=0;i<length;i++) { data=x[i]; insert_BS_tree_inverse(&t_inverse,data); } printf("\n二叉排序树反序排序后的中序遍历结果:\n"); inorder_tree(t_inverse.root); } 1. 程序流程说明: 初始化二叉树 ——> 创建哈夫曼树 ——> 求出哈夫曼编码 ——> 结束 程序文件名为ex4_4.cpp,源程序清单如下: #include <stdio.h> #include <stdlib.h> static int hfmb=0; struct tree { char date;//数据 bool min;//叶子节点 int quanzhi;//权值 struct tree *Lchild,*Rchild;//左右孩子 }*Tree; struct shfm { char date;//字符数据 char bianm[16];//哈夫曼编码,最大编码数为11(可根据实际修改!) }hfm[100];//哈夫曼编码对应真实数据表 void getTree(tree tr[],int shij,int youx)//构造哈夫曼树,tr树集合,shij集合实际数据个数,youx集合有效数据个数 { //模拟动态增长数组,每次构造新的树就插入有效数据后面 if (2*youx-1!=shij) { printf("参数不符合!"); return; } int c=0; while(youx!=shij)//当有效个数==实际个数时,构造完成! { for (int i=c;i<youx;i++) { //每次循环取两个最小值并将两个最小值放置在当前循环起始两位 if (tr[i].quanzhi<tr[c].quanzhi) { tree p=tr[i]; tr[i]=tr[c]; tr[c]=p; } if (tr[i].quanzhi<tr[c+1].quanzhi) { tree p=tr[i]; tr[i]=tr[c+1]; tr[c+1]=p; } } //以下为通过最小值构造的新树 tr[youx].quanzhi=tr[c].quanzhi+tr[c+1].quanzhi; tr[youx].Rchild=&tr[c];//新树右孩子指向当前循环的最小值之一 tr[youx].Lchild=&tr[c+1];//新树左孩子指向当前循环的最小值之一 youx++;//新树插入当前有效数据个数后面 并使有效数据个数+1 c=c+2; } } void bianlTree(tree *tr,char ch[])//哈夫曼编码 { //通过遍历树,得到每个节点的编码 static int i=0; if (!tr->min)//叶子节点 { ch[i]='0'; i++; bianlTree(tr->Lchild,ch);//左节点编码为"0" ch[i]='1'; i++; bianlTree(tr->Rchild,ch);//右节点编码为"1" } if (tr->min) { ch[i]='\0';//结束标记() printf("%c %s \n",tr->date,ch); hfm[hfmb].date=tr->date; int j=0; while(j!=i||i>10) { hfm[hfmb].bianm[j]=ch[j]; j++; }//保存编码映射表 hfmb++; } i--;//递归走入右叶子节点时,取消当前赋值(当前必为左边叶子节点) } int main() { tree tr[13]={{'a',true,115},{'b',true,11},{'c',true,14},{'d',true,35},{'e',true,516},{'f',true,254},{'g',true,55}}; // printf("%d \n",sizeof(tr)/sizeof(Tree)); getTree(tr,13,7); char ch[100]; //printf("%s\n",ch); bianlTree(&tr[12],ch); return 0; } 程序流程说明: 1.1查找流程和程序实现说明: 顺序查找:从第一个数据元素开始,逐个把数据元素的关键字值与给定值比较,若某个元素的关键字值与给定值相等,则查找成功;否则,,若直至第n个数据元素都不相等,说明不存在满足条件的数据元素,查找失败。 二分查找:先将查找表中的数据元素按照关键字进行排序,则在查找中采用跳跃的方式——先与中间位置的数据元素的关键字进行比较,若相等,则查找成功,若给定值大于中间位置的数据元素,则在查找表的后半部进行二分查找,否则,在查找表的前半部进行二分查找。 哈希查找: 先构造哈希表 ——>确定数据元素的存储地址 ——>比较关键字的哈希值和地址的对照表,即可得到 。 1.2排序流程和程序实现说明: 简单选择排序: 第一趟在无序表中按照排序码选出最小的元素,将它与R1交换;第二趟排序是在无序的表中选出最小的元素,将它与R2交换,而第i趟排序时,再选出最小的元素,将它与Ri元素交换,是R1-Ri成为有序。直到整个表有序。 简单插入排序: 把n个数据元素的序列分为两部分,一个是已经排好序的有序部分,一个是未排序部分。这时,把未排序部分的一个元素一次与已经排好序的元素比较,并插入到有序部分的合适位置上,使得这些元素变为新的有序部分。 冒泡排序: 从第一个元素开始,两两比较第i和i+1元素的排序码的大小,若排序码i>i+1,则交换第i个元素和第i+1个元素的位置。第一趟全部比较完毕后第n个元素是序列最大的数据元素,如此反复,进行n-1趟冒泡排序后所有待排序的n个元素序列按排序码有序。 快速排序: 从待排序的n个元素中任意选取一个元素作为标准,调整序列中各个元素的位置,使得排在它前面的元素的排序吗都小于它的排序码,排在它后面的元素的排序码都大于它的排序码,如此反复,直到全部元素排序完毕。 源程序清单如下: Search.cpp: /*******************************Copyright (c)********************************************* ** University of Electronic Science and Technology of China ** School of Communication and Information Engineering ** http://www.uestc.edu.cn ** **--------------------------- File Info --------------------------------------------------- ** File name: search.cpp ** Last modified Date: 2012-12-19 ** Last Version: 1.0 ** Descriptions: 各种检索操作,顺序表结构的定义在mystruct.h中, ** 函数中使用的与界面显示有关接口的说明在ui.h ** 本文件基于C语言风格 **------------------------------------------------------------------------------------------ ** Created by: Duan Jingshan ** Created date: 2012-12-19 **------------------------------------------------------------------------------------------ ** Modified by: ** Modified date: ** Version: ** Descriptions: ** *******************************************************************************************/ #include "stdafx.h" #include "mystruct.h" #include "ui.h" #include<string.h> /******************************************************************************************* ** Function name: sequence_search() ** Descriptions : 顺序检索 ** 在顺序表中找到指定元素后,将元素值取出,放置到指定内存中,可能需要使用memcpy() ** Input: ** table_t * table; 顺序表指针 ** double stuNum; 待查询元素的关键字——学号 ** Output: ** element_t * elem; 用于存放指定元素内容的内存指针 ** return: 类型:int;待查元素在顺序表中的序号(从0开始),-1查询失败 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ int sequence_search(table_t * table, double Num, element_t * elem) { int i=0; for(i=0;i<table->length;i++) { if(table->data[i].stuID==Num) { memcpy(elem,&(table->data[i]),sizeof(element_t)); return i; } } return -1; } /******************************************************************************************* ** Function name: binaray_search() ** Descriptions : 二分检索 ** 在顺序表中找到指定元素后,将元素值取出,放置到指定内存中,可能需要使用memcpy() ** Input: ** table_t * table; 顺序表指针 ** double stuNum; 待查询元素的关键字——学号 ** Output: ** element_t * elem; 用于存放指定元素内容的内存指针 ** return: 类型:int;待查元素在顺序表中的序号(从0开始),-1查询失败 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ int binary_search(table_t * table, double Num, element_t * elem) { int low=0,high=table->length-1,mid=0; int i=0,j=0; int flag=0; // element_t t; // element_t data[40]; /* for(i=0;i<table->length;i++) { data[i].stuID=table->data[i].stuID; } for(i=0;i<table->length;i++) { for(j=i;j<table->length-1;j++) { if(table->data[j].stuID>table->data[j+1].stuID) { t=table->data[j]; table->data[j]=table->data[j+1]; table->data[j+1]=t; } } } */ /* for(i=0;i<table->length;i++) { if(table->data[i].stuID==Num) { // memcpy(elem,&(table->data[i]),sizeof(element_t)); flag=i; } } */ while(low<=high) { mid=(low+high)/2; if(table->data[mid].stuID==Num) { memcpy(elem,&(table->data[mid]),sizeof(element_t)); //flag=table->data[mid].stuID; return mid; } else if(table->data[mid].stuID<Num) low=mid+1; else high=mid-1; } /* for(i=0;i<table->length;i++) { if(data[i].stuID==flag) return i; } */ return -1; } /******************************************************************************************* ** Function name: hash() ** Descriptions : 计算关键字的哈希值,即按照设定的Hash公式计算出关键字经过Hash运算后的结果 ** 本算法设定的Hash公式仿照Daniel J.Bernstein 教授设计的DJB算法,以学生姓名 ** 的字符串为输入关键字完成计算,然后再采用截断法,将结果的最后五位(二进制) ** 输出,即获得0~31之间的Hash结果。 ** DJB算法: ** 设输入为a(1),a(2),……a(n)这样的字节流(字符串), ** hash(0) = 5381; ** hash(i) = (hash(i-1)*32 + hash(i-1)) + a(i) for i = 1 to n ** result = hash(n) & 0x1f; ** ** Input: ** char * stu_name; 学生姓名字符串 ** Output: ** return: 类型:int; Hash运算结果, 0 ~ 31 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ int hash(char * stu_name) { int i; long hash = 5381; for( i = 0; i < (int)strlen(stu_name) ; i ++){ hash = ((hash << 5) + hash) + (long)stu_name[i]; } return (int)(hash & 0x1f); } /******************************************************************************************* ** Function name: hash_search() ** Descriptions : hash检索, 根据关键字计算出的hash值对hash表进行检索。 ** hash表中,学号为0表示该位置没有填写有效的内容 ** 冲突解决方法为线性探查法 ** Input: ** table_t * table; 顺序表指针 ** char * stu_name; 待查询元素的关键字——姓名 ** Output: ** element_t * elem; 用于存放指定元素内容的内存指针 ** return: 类型:int;待查元素在顺序表中的序号(从0开始),-1查询失败 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ int hash_search(table_t *table, char * stu_name, element_t * elem) { int p=0,t=0,i=0; int a[40]; p=hash(stu_name); for (i=0;i<table->length;i++) { a[i]=hash(table->data[i].stuName); if(a[i]==p&&strcmp(table->data[i].stuName,stu_name)==0) { memcpy(elem,&(table->data[i]),sizeof(element_t)); return i; } } //table->data[33].pinshi=0; //while(strcmp(table->data[p].stuName,stu_name)==1) //&&strcmp(table->data[p].stuName,sstu_name)==1 // for(t=p;table->data[p].pinshi!=0;t++) // { /*if(strcmp(table->data[p].stuName,stu_name)==0) { memcpy(elem,&(table->data[p]),sizeof(element_t)); return p; }*/ // } return -1; } /******************************************************************************************* ** Function name: hash_insert() ** Descriptions : hash插入, 根据关键字计算出的hash值,将元素插入到hash表中。 ** 冲突解决方法为线性探查法 ** Input: ** table_t * table; 顺序表指针 ** element_t elem; 新元素 ** Output: ** return: 类型:int ; 插入结果,0表示成功,-1表示失败。 ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ int hash_insert(table_t *table, element_t elem) { int t=0; t=hash(elem.stuName); while(table->data[t].pinshi!=NULL) { t=(t+1)%40; } table->data[t]=elem; return 0; } Sort.cpp /*******************************Copyright (c)********************************************* ** University of Electronic Science and Technology of China ** School of Communication and Information Engineering ** http://www.uestc.edu.cn ** **--------------------------- File Info --------------------------------------------------- ** File name: sort.cpp ** Last modified Date: 2012-12-19 ** Last Version: 1.0 ** Descriptions: 各种排序操作,针对顺序表进行排序,顺序表结构的定义在mystruct.h中, ** 函数中使用的与界面显示有关接口的说明在ui.h ** 本文件基于C语言风格 **------------------------------------------------------------------------------------------ ** Created by: Duan Jingshan ** Created date: 2012-12-19 **------------------------------------------------------------------------------------------ ** Modified by: ** Modified date: ** Version: ** Descriptions: ** *******************************************************************************************/ #include "stdafx.h" #include "mystruct.h" #include "ui.h" /******************************************************************************************* ** Function name: simple_insert_sort() ** Descriptions : 简单插入排序,按总成绩从小到大排序 ** ** Input: ** table_t * table; 顺序表指针 ** Output: ** table_t * table; 排序后的顺序表 ** return: 类型:void; ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ void simple_insert_sort(table_t * table) { int i,j; element_t a; for(i=0;i<table->length-1;i++) { a=table->data[i+1]; j=i; while(j>-1&&a.overall<table->data[j].overall) { table->data[j+1]=table->data[j]; j--; } table->data[j+1]=a; } } /******************************************************************************************* ** Function name: simple_insert_sort() ** Descriptions : 简单插入排序,按总成绩从小到大排序 ** ** Input: ** table_t * table; 顺序表指针 ** Output: ** table_t * table; 排序后的顺序表 ** return: 类型:void; ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ void simple_select_sort(table_t * table) { int i=0; int j=0; int sma=0; element_t temp; for(i=0;i<table->length-1;i++) { sma=i; for(j=i+1;j<table->length;j++) { if(table->data[j].overall<table->data[sma].overall) sma=j; } if(sma!=i) { temp=table->data[i]; table->data[i]=table->data[sma]; table->data[sma]=temp; } } } /******************************************************************************************* ** Function name: simple_insert_sort() ** Descriptions : 简单插入排序,按总成绩从小到大排序 ** ** Input: ** table_t * table; 顺序表指针 ** Output: ** table_t * table; 排序后的顺序表 ** return: 类型:void; ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ void bubble_sort(table_t * table) { int i,j,flag; element_t swap; flag=1; for(i=0;i<table->length-1&&flag==1;i++) { flag=0; for(j=0;j<table->length-i;j++) if(table->data[j].overall>table->data[j+1].overall) { flag=1; swap=table->data[j]; table->data[j]=table->data[j+1]; table->data[j+1]=swap; } if(flag==0) return; } } /******************************************************************************************* ** Function name: quick_sort() ** Descriptions : 快速排序,按总成绩从小到大排序,这是一种递归算法 ** ** Input: ** table_t * table; 顺序表指针 ** int first; 排序范围的上边沿 ** int last; 排序范围的下边沿 ** Output: ** table_t * table; 排序后的顺序表 ** return: 类型:void; ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ void quick_sort(table_t * table,int first, int last) { int i,j; element_t swap; i=first; j=last; swap=table->data[first]; while(i<j) {while(i<j&&(swap.overall<=table->data[j].overall)) j--; if(i<j) { table->data[i]=table->data[j]; i++; } while(i<j&&(swap.overall>=table->data[i].overall)) i++; if(i<j) { table->data[j]=table->data[i]; j--; } } table->data[i]=swap; if(first<i) quick_sort(table,first,last-1); if(i<last) quick_sort(table,j+1,last); } 六、实验内容: ex5_2:Hash查找——扩展题 1)一个班有30位同学,安排装进一个有30个元素的数组,以姓名作为关键字进行哈希存储,具体方法如下:将姓名字符串中的每个字节按ASCII码(中文也支持 的哦)加起来,除以30,取得的余数作为元素存放位置(数组下标)。冲突解决采用线性探查法。 2)输入少于30个学生姓名,按Hash方式存入表中。 3)验证能够按Hash方式找到表中学生,不在表中将提示错误 ex5-4:编写快速排序函数(见实验报告:查找和排序基础) ex5-4:归并排序——扩展题(选作) 1)两个有序的顺序表,共用1个空间,存放时两个表是连续的,即表A先存放,接着是表B,编写合并函数,合并成一个有序的顺序表,在原表上完成。 2)编写归并排序函数,先以每个元素为子表,两两归并——调用合并函数,然后继续把新表两两合并,直到最后合并成一个大表,完成归并排序 3)main函数中输入一组无序数,调用归并排序函数,进行排序,并显示排序结果。 源程序清单如下: Ex5_2.cpp: #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> //1)一个班有30位同学,安排装进一个有30个元素的数组,以姓名作为关键字进行哈希存储, //具体方法如下:将姓名字符串中的每个字节按ASCII码(中文也支持 的哦)加起来,除以30,取得的余数作为元素存放位置(数组下标)。冲突解决采用线性探查法。 //2)输入少于30个学生姓名,按Hash方式存入表中。 //3)验证能够按Hash方式找到表中学生,不在表中将提示错误 struct Student { char a[100]; int age; }; int hash(char *cp) { int sum=0,yushu; int n=0; int i=0; n=strlen(cp); for(i=0;i<n;i++) { sum+=(int)*cp; cp++; } sum=abs(sum); yushu=sum%30; return yushu; } int hash_table(Student *student,int n) { int i=0,xuh=0; for(i=0;i<n;i++) { xuh=hash(student[i].a); // printf("%d\t",xuhao); if(student[xuh].age!=NULL) { xuh=(xuh+1)%30; } //printf("%d",xuh); student[xuh]=student[i]; } return 0; } int hash_search(char *name, char * stu_name,int n) { int p=0,t=0,i=0; int a[40]; p=hash(stu_name); for (i=0;i<n;i++) { a[i]=hash(name); if(a[i]==p&&strcmp(name,stu_name)==0) { return i; } } return -1; } int main() { Student stu[30]; char name[100]; int i,j; int n,xuhao; int flag=-1; printf("您将输入多少个学生信息?"); scanf("%d",&n); printf("\n请输入学生姓名和年龄:\n"); for(i=0;i<n;i++) { scanf("%s",&stu[i].a); scanf("%d",&stu[i].age); } printf("您输入的学生姓名和年龄信息如下:\n"); for(i=0;i<n;i++) printf("%s\t%d\n",stu[i].a,stu[i].age); hash_table(stu,n); // for(i=0;i<n;i++) // { // xuhao=hash(stu[i].a); // printf("%d\t",xuhao); // } printf("请输入需要查找的姓名:"); scanf("%s",&name); for (i=0;i<n;i++) { flag=hash_search(stu[i].a,name,n); if(flag!=-1) { printf("已找到"); return 0; } } printf("未找到"); return -1; } Ex5_4:快排 /******************************************************************************************* ** Function name: quick_sort() ** Descriptions : 快速排序,按总成绩从小到大排序,这是一种递归算法 ** ** Input: ** table_t * table; 顺序表指针 ** int first; 排序范围的上边沿 ** int last; 排序范围的下边沿 ** Output: ** table_t * table; 排序后的顺序表 ** return: 类型:void; ** Created by : ** Created Date : **------------------------------------------------------------------------------------------ ** Modified by : ** Modified Date: **------------------------------------------------------------------------------------------ *******************************************************************************************/ void quick_sort(table_t * table,int first, int last) { int i,j; element_t swap; i=first; j=last; swap=table->data[first]; while(i<j) {while(i<j&&(swap.overall<=table->data[j].overall)) j--; if(i<j) { table->data[i]=table->data[j]; i++; } while(i<j&&(swap.overall>=table->data[i].overall)) i++; if(i<j) { table->data[j]=table->data[i]; j--; } } table->data[i]=swap; if(first<i) quick_sort(table,first,last-1); if(i<last) quick_sort(table,j+1,last); } Ex5_4选做 #include <stdio.h> #include <stdlib.h> //交换函数,将a,b交换 void swap(int *a,int *b){ int temp; temp=*a; *a=*b; *b=temp; } //反序函数,将数组各元素反序排列 void reverse_array(int a[], int n) { int i=0; int j=n-1; while (i<j) { swap(&a[i], &a[j]); i++; j--; } } //交换函数,将数组进行一次重排。 void exchange(int a[], int length, int length_left) { reverse_array(a, length_left); reverse_array(a+length_left,length-length_left); reverse_array(a, length); } //归并函数 ,找出前一个大于后一个的元素,将其交换 void Merge(int a[],int begin,int mid,int end){ while (begin<mid&&mid<=end){ int step=0; while (begin<mid&&a[begin]<=a[mid]) begin++; while (mid<=end&&a[mid]<=a[begin]){ mid++; step++; } exchange(a+begin,mid-begin,mid-begin-step); } } //确定两两归并的元素序号 void MergeCore(int a[], int left, int right) { if (left<right){ int mid = (left + right) / 2; MergeCore(a, left, mid); MergeCore(a, mid + 1, right); Merge(a, left, mid + 1, right); } } //从第一个元素和最后一个元素开始,分——合 void MergeSort(int a[], int length) { if (a == NULL || length < 1) return; MergeCore(a, 0, length - 1); } //主函数,自定义输入,前6个为有序的,后6个为有序的,整个数组是无序的。 int main() { int a[] = {1,5,9,11,16,24,2,8,14,15,21,27}; //计算数组的长度 int length = sizeof(a) / sizeof(int); MergeSort(a, length); for (int i = 0; i < length; i++) printf("%d ",a[i]); printf("\n"); return 0; }
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。