/*
源文件名:P1.cpp
功能:静态线性表操作
*/
#include<stdio.h>
# include <iostream>
using namespace std;
#include <iomanip>
#include <stdlib.h>
#include<conio.h>
#include <process.h>
#include <string.h>
#include <math.h>
const int Max=10000;
int Qc1,Qc2;//Qc1,Qc2分别是快速排序的比较次数和移动次数
struct SqList
{
int elem[Max]; //存放元素的数组
int length; //当前长度
};
void init(SqList &list);
void display(SqList &list);
void insert(SqList &list);
void search(SqList &list);
void del(SqList &list);
void simpleSort(SqList &list);//简单选择排序
int Partition(SqList &list,int low,int high);//返回轴枢,并且将轴枢记录到位
void quickSort(SqList &list,int low,int high);//快速排序
void binarySearch(SqList &list);//折半查找
void reverseList(SqList &list); //就地逆置顺序表
void sortedInsert(SqList &list);//有序插入
void del_x_y(SqList &list,int x,int y);//删除指定区间元素知
void mergeList(SqList &La,SqList &Lb,SqList &Lc); //合并非递减顺序表
void shellSort(SqList &list);//希尔排序
void adjustHeap(SqList &list,int s,int m);//堆调整
void heapSort(SqList &list);//堆排序
SqList list;
SqList Lb,Lc;//lb为要与list进行合并的顺序表,Lc为合并后的新表
int main()
{
int choice;
int sortedFlag=0;//1表示顺序表已经经过排序,0表示顺序表尚未排序 ,每插入一个元素,都将视为表未经排序
while (1)
{
system("cls");
cout << "\n\n\n\n";
cout << "\t\t 静态线性表操作 \n";
cout << "\t\t======================================";
cout << "\n\n";
cout << "\t\t 1:初始化 \n";
cout << "\t\t 2:显示 \n";
cout << "\t\t 3:单个插入 \n";
cout << "\t\t 4:查找 \n";
cout << "\t\t 5:删除 \n";
cout << "\t\t 6:简单排序 \n";
cout << "\t\t 7:快速排序 \n";
cout << "\t\t 8:折半查找 \n";
cout << "\t\t 9:就地逆置 \n";
cout << "\t\t 10:有序插入 \n";
cout << "\t\t 11:删除顺序表中元素值在x到y(x和y自定)之间的所有元素 \n";
cout << "\t\t 12:将两个非递减的顺序表进行合并 \n";
cout << "\t\t 13:希尔排序 \n";
cout << "\t\t 14:堆排序 \n";
cout << "\n";
cout << "\t\t 0:退出 \n";
cout << "\n";
cout << "\t\t请选择:" << flush;
scanf("%d",&choice);//用户如果不小心输入了自己不想执行功能的序号,程序不会立即执行该功能,按下回车后才会执行,用户有重新输入的余地,
system("cls");
switch(choice)
{
case 1:
{
init(list);
display(list);
}
break;
case 2:
display(list);
break;
case 3:
{
insert(list);
sortedFlag=0;
}
break;
case 4:
{
if(list.length==0)
{
printf("表中没有元素,请初始化为非空表或插入数值后再试!\n");
system("pause");
break;
}
search(list);
system("pause");
}
break;
case 5:
if(list.length==0)
{
printf("表中没有元素,请初始化为非空表或插入数值后再试!\n");
system("pause");
break;
}
del(list);
display(list);
break;
case 6:
{
if(list.length==0)
{
printf("表中没有元素,请初始化为非空表或插入数值后再试!\n");
system("pause");
break;
}
simpleSort(list);
sortedFlag=1;//排序后,变为1
}
break;
case 7:
{
if(list.length==0)
{
printf("表中没有元素,请初始化为非空表或插入数值后再试!\n");
system("pause");
break;
}
Qc1=0,Qc2=0;
quickSort(list,0,list.length-1);
sortedFlag=1;//排序后,变为1
printf("快速排序成功!\n比较次数:%d\n移动次数:%d\n\n",Qc1,Qc2);
display(list);
}
break;
case 8:
{
if(list.length==0)
{
printf("表中没有元素,请初始化为非空表或插入数值后再试!\n");
system("pause");
break;
}
if(sortedFlag==0)
{
printf("此时的顺序表尚未排序!无法进行折半查找!\n");
system("pause");
break;
}
binarySearch(list);
system("pause");
}
break;
case 9:
if(list.length==0)
{
printf("表中没有元素,请初始化为非空表或插入数值后再试!\n");
system("pause");
break;
}
reverseList(list);
sortedFlag=0;//逆置后,默认表为无序,不管之前是否经过了排序
break;
case 10:
{
if(list.length==Max||sortedFlag==0)
{
if(list.length==Max)
{
printf("顺序表已满!无法插入!\n");
}
if(sortedFlag==0)
{
printf("尚未进行排序!无法进行有序插入!\n");
}
system("pause");
break;
}
sortedInsert(list);
display(list);
system("pause");
}
break;
case 11:
{
if(list.length==0)
{
printf("表中没有元素,请初始化为非空表或插入数值后再试!\n");
system("pause");
break;
}
int x,y;
cout << "11:删除顺序表中元素值在x到y(x和y自定)之间的所有元素(x<=y) \n(不论是否进行过排序,都可以进行此操作)\n";
printf("请输入x:");
scanf("%d",&x);
printf("请输入y:");
scanf("%d",&y);
if(x>y)
{
printf("输入有误!x不能大于y!\n");
system("pause");
break;
}
del_x_y(list,x,y);
display(list);
}
break;
case 12:
{
if(list.length==0)
{
printf("表中没有元素,请初始化为非空表或插入数值后再试!\n");
system("pause");
break;
}
mergeList(list,Lb,Lc);//将非递减list与Lb合并为Lc
display(Lc);//显示合并后的情况
list=Lc; //将合并后的顺序表覆盖掉原来的顺序表,以便对合并后的顺序表进行显示,查找,删除等操作
}
break;
case 13:
{
if(list.length==0)
{
printf("表中没有元素,请初始化为非空表或插入数值后再试!\n");
system("pause");
break;
}
shellSort(list);
display(list);
}
break;
case 14:
{
if(list.length==0)
{
printf("表中没有元素,请初始化为非空表或插入数值后再试!\n");
system("pause");
break;
}
heapSort(list);
display(list);
}
break;
case 0:
exit(0);
default :
{
printf("输入的数字有误!请重新输入!\n");
system("pause");
}
break;
}
}
return 0;
}
//屏幕提示后,从键盘输入线性表长度和随机数种子,生成指定长度的线性表list
void init(SqList &list)
{
int i;
while (1)
{
cout << "输入元素个数(0-" << Max << "):" << flush;
cin >> list.length;
if (list.length >= 0 && list.length <= Max)
break;
cout << endl;
}
while (1)
{
cout << "输入随机数种子(0-32767):" << flush;
cin >> i;
if (i >= 0 && i <= 32767)
break;
cout << endl;
}
srand(i); //指定随机数种子,相同的种子将产生相同的数据序列
rand();
for (i = 0; i < list.length; i++)
{
list.elem[i] = rand() % 10000;
}
for (i = list.length; i < Max; i++)
list.elem[i] = 0;
printf("初始化成功!\n\n");
}
//在屏幕上依次显示线性表list中的元素个数和全部元素
//格式应便于观察
//如果需要指定输出的宽度,可以使用 %md其中 m 是占据的列数,如果加上-号,则会向左对齐
void display(SqList &list)
{
if(list.length==0)
{
printf("此时表中没有元素!\n\n");
}
int i;
printf("线性表中元素个数:%d\n",list.length);
printf("Tips:为显示清楚,每行显示五个元素。\n");
printf("全部元素:\n");
for(i=0;i<list.length;i++)
{
if(i%5==0)//每行显示5个
{
printf("\n");
}
printf("%-4d\t",list.elem[i]);
}
printf("\n\n");
system("pause");
}
//屏幕提示后,从键盘输入一个元素值,然后把这个新元素插到线性表list的末尾
//应有溢出判断和报告
void insert(SqList &list)
{
if(list.length==Max)
{
printf("线性表已满!无法插入!\n");
system("pause");
return ;
}
int x;
printf("请输入要插入的元素:");
scanf("%d",&x);
list.elem[list.length]=x;//插入数值
list.length++;//表长加一
printf("已成功插入到末尾!\n\n");
display(list);
}
//屏幕提示后,从键盘输入一个元素值,在线性表list中搜索这个元素
//屏幕显示搜索结果和搜索过程中的比较次数
void search(SqList &list)//如果顺序表中有重复元素,要想查找出所有与输入数值相同的元素,则比较次数就是固定的,为表的长度
{
int flag=0;//0表示查找失败,1表示查找成功
int x;
int i;
int count=0;//保存比较次数
printf("\nTip:系统默认只查找出第一个(按下标从小到大的顺序)与输入数值相同的元素\n\n请输入要查找的数值:");
scanf("%d",&x);
for(i=0;i<list.length;i++)
{
count++;
if(x==list.elem[i])
{
printf("查找成功!\n");
printf("\nlist.elem[%d]=%d\n\n",i,x);
flag=1;
break;
}
}
if(flag==0)
{
printf("查找失败!未找到您输入的数值!\n");
}
printf("比较次数:%d\n",count);
if(flag==1)
{
printf("顺序表中可能有重复的元素,是否进行全盘查找(找出所有与输入数值相同的元素)?\n\n");
printf("\t\t\t1-是\t0-否\n");
int choice;
scanf("%d",&choice);
switch(choice)
{
case 1:
{
printf("所有与输入元素值相同的元素如下:\n\n");
for(i=0;i<list.length;i++)
if(x==list.elem[i])
printf("list.elem[%d]=%d\n",i,x);
printf("\n全盘查找的比较次数就是表的长度list.length=%d\n",list.length);
}
break;
case 0:
printf("已取消全盘查找!\n");break;
}
}
}
//屏幕提示后,从键盘输入一个元素值,在线性表list中删除这个元素
//屏幕显示删除成功与否的信息,并显示比较次数和移动次数
void del(SqList &list)//表中可能存在重复的元素 不足:不能删除所有重复的元素
{
int x;
int flag=0,i,j,c1=0,c2=0;//c1为比较次数,c2为移动次数 ,
printf("请输入要删除的数值:");
scanf("%d",&x);
for(i=0;i<list.length;i++)
{
c1++;
if(x==list.elem[i])
{
flag=1;
for(j=i;j<list.length-1;j++)
{
c2++;
list.elem[j]=list.elem[j+1];
}
list.length--;
printf("删除成功!\n比较次数:%d,移动次数:%d\n",c1,c2);
break;
}
}
if(flag==0)
printf("表中没有该元素,删除失败!\n比较次数:%d,移动次数:%d\n",c1,c2);
}
//对线性表list进行简单排序
//屏幕显示比较次数和移动次数
void simpleSort(SqList &list)
{
int x,i,j,k,min;//x作为交换中介,min保存下标i到list.length-1 (0<=i<=list.length-1)最小元素的下标
int c1=0,c2=0;//c1保存比较次数,c2保存交换次数
for(i=0;i<list.length-1;i++)
{
min=i;//先假设第下标为i的个元素就是最小的,
for(j=i+1;j<list.length;j++)//找出i到list.length-1最小元素的下标
{
c1++;
if(list.elem[j]<list.elem[min])//遇到更小的min就变成更小的元素的下标
min=j;
}
if(min!=i)//如果第i个元素不是最小的,就和min交换
{
c2++;
x=list.elem[min];
list.elem[min]=list.elem[i];
list.elem[i]=x;
}
}
printf("简单选择排序成功!结果如下:\n\n比较次数:%d,\n移动次数:%d\n\n",c1,c2);
display(list);
}
int Partition(SqList &list,int low,int high)//返回轴枢,并且将轴枢记录到位
{
int x;
x=list.elem[low];
while(low<high)
{
while(low<high&&x<=list.elem[high])
{
Qc1++;
high--;
}
if(list.elem[low] != list.elem[high]) //不相等时,才会移动
{
list.elem[low]=list.elem[high];//将后面较小的数移到前面
Qc2++;
}
while(low<high&&x>=list.elem[low])
{
Qc1++;
low++;
}
if(list.elem[high] != list.elem[low])//不相等时,才会移动
{
list.elem[high]=list.elem[low]; //将前面较大的数移到后面
Qc2++;
}
}
list.elem[low]=x;
return low;
}
//对线性表list进行快速排序
//屏幕显示比较次数和移动次数
void quickSort(SqList &list,int low,int high)
{
int pivotloc;
if(low<high)
{
pivotloc = Partition(list,low,high);
quickSort(list,low,pivotloc-1);
quickSort(list,pivotloc+1,high);
}
}
//屏幕提示后,从键盘输入一个元素值,对经过排序的线性表list进行折半查找
//屏幕显示查找结果,并显示比较次数
void binarySearch(SqList &list)
{
printf("请输入要进行折半查找的数值:");
int x;
scanf("%d",&x);
int low=0,high=list.length-1,mid;//low和high初始时分别在第一个和最后一个元素
int count = 0; //count保存比较次数
while(low<=high)//当low不大于high都能进行查找
{
mid=(low+high)/2;
count++;//每执行一次循环,就和一个元素进行比较
if(x==list.elem[mid])
{
printf("折半查找成功!\n比较次数:%d\n",count);
printf("\nlist.elem[%d]=%d\n\n",mid,x);
return; //找到元素后,就返回主函数
}
else
{
if(x<list.elem[mid])
{
high=mid-1;
}
else
{
low=mid+1;
}
}
}
printf("未找到您输入的数值,折半查找失败!\n比较次数:%d\n",count);
}
void reverseList(SqList &list)//就地逆置
{
int x;//逆置的交换媒介
int low=0,high=list.length-1;//low和high分别在首尾
while(low<high)//当low不大于high时下标low与high上的元素交换
{
x=list.elem[low];
list.elem[low]=list.elem[high];
list.elem[high]=x;
low++;
high--;
}
printf("逆置后的情况:\n\n");
display(list);
}
//屏幕提示后,从键盘输入一个元素值,在经过排序的线性表中插入这个元素;
//屏幕显示比较次数和移动次数,应有溢出判断和报告
void sortedInsert(SqList &list)
{
printf("请输入要进行有序插入的元素值:");
int x,xPosition;
scanf("%d",&x);
int i=0,c1=0,c2=0;//c1 c2分别为比较次数和移动次数
for(i=0;i<list.length;i++)//循环结束后i就是x所要插入的位置
{
c1++;
if(list.elem[i]>x)//比较一次
break;
}
xPosition=i;
//找到x要插入的位置
//接着进行元素移动,将下标为i到list.length-1的元素全部向后移动一位,将x插入
for(i=list.length-1;i>=xPosition;i--)
{
c2++;
list.elem[i+1]=list.elem[i];//移动一次
}
list.elem[xPosition]=x;//插入x
list.length++;//插入后表长加一
printf("有序插入成功!\n比较次数:%d\n移动次数:%d\n\n",c1,c2);
}
//以较高的效率实现删除顺序表中元素值在x到y(x和y自定)之间的所有元素
//无需进行排序,就能进行较高效率的删除操作
void del_x_y(SqList &list,int x,int y)//借鉴CSDN上的代码
{
int i,j;
int formerLength=list.length; //保存顺序表初始长度
for(i=j=0;i<formerLength;i++)
{
if(list.elem[i]<x||list.elem[i]>y)//如果不在x-y范围内,元素将按照原来的次序保留在数组中
{
list.elem[j]=list.elem[i];
j++;
}
else
list.length--; //如果在x-y范围内,表长减一
//最终顺序表中所有元素都不在x-y范围内,不需要进行排序,也不需要大批量移动(只有一重循环),就实现了较高效率的删除
}
for (i = list.length ; i < formerLength; i++)//删除完成后,不该存在数据的原表中的位置归零
list.elem[i] = 0;
if(list.length==formerLength)
printf("表中没有元素在x-y之间,删除失败!\n\n");
else
printf("删除成功!\n\n");
}
//编程实现将两个非递减的顺序表进行合并,要求同样的数据元素只出现一次;
void mergeList(SqList &La,SqList &Lb,SqList &Lc)
{
quickSort(La,0,La.length-1);//对La进行排序,确保La参加合并时是非递减的
printf("第一个非递减顺序表:\n\n");
display(La);
printf("还需要您手动初始化第二个顺序表\n\n");
init(Lb);
quickSort(Lb,0,Lb.length-1);//对Lb进行排序,确保Lb参加合并时是非递减的
printf("第二个非递减顺序表:\n\n");
display(Lb);
//有两个符合条件的表,就能开始合并了
int i=0,j=0,k=0;
while(i<La.length&&j<Lb.length)//按顺序把两表中较小的元素插到Lc中
{
while(i+1<La.length&&La.elem[i]==La.elem[i+1])//若La中有重复元素 ,则i移动到重复元素的最后位置,防止Lc中出现重复
{
i++;
}
while(j+1<Lb.length&&Lb.elem[j]==Lb.elem[j+1])//若Lb中有重复元素 ,则j移动到重复元素的最后位置,防止Lc中出现重复
{
j++;
}
if(La.elem[i]<Lb.elem[j])
{
Lc.elem[k]=La.elem[i];
i++;
k++;
}
else
if(La.elem[i]>Lb.elem[j])
{
Lc.elem[k]=Lb.elem[j];
j++;
k++;
}
else //若la和Lb中存在某个相同的元素,则 i,j都要后移,以防止出现重复元素
{
Lc.elem[k]=La.elem[i];
i++;
j++;
k++;
}
}
//当某一表遍历完时,将未遍历的表全部插入到新表中
while(i<La.length)
{
while(i+1<La.length&&La.elem[i]==La.elem[i+1])//若La中有重复元素 ,则i移动到重复元素的最后位置,防止Lc中出现重复
{
i++;
}
Lc.elem[k]=La.elem[i];
i++;
k++;
}
while(j<Lb.length)
{
while(j+1<Lb.length&&Lb.elem[j]==Lb.elem[j+1])//若Lb中有重复元素 ,则j移动到重复元素的最后位置,防止Lc中出现重复
{
j++;
}
Lc.elem[k]=Lb.elem[j];
j++;
k++;
}
Lc.length=k;//易知最后k的大小就是Lc表长
for(i=Lc.length;i<Max;i++)//数组Lc.elem[Max]没有指定元素的位置归零
{
Lc.elem[i]=0;
}
printf("合并成功!合并后的表如下所示:\n\n");
}
//希尔排序(步长为5,3,1)
void shellSort(SqList &list)
{
int x;
int i,k,j;
int d[3]={5,3,1};
for(k=0;k<3;k++)
{
for(i=d[k];i<list.length;i++)
{ //如果 list.elem[i]>list.elem[i-d[k]],则无需向前插入,直接保持在原位就行
if(list.elem[i]<list.elem[i-d[k]])//如果list.elem[i]<list.elem[i-d[k]],则需要向前找到list.elem[i]的位置
{
x=list.elem[i];//x暂存list.elem[i]
for(j=i-d[k];j>=0&&x<list.elem[j];j=j-d[k]) //若j-d[k]<0,则j已经到达子序列的第一个位置
list.elem[j+d[k]]=list.elem[j];//比x大的都要向后移动
//若结束循环后j仍然大于等于与0,则此时x>= list.elem[j],此时,比x大的都已经向后移动了,j+d[k]就是x要插入的位置 ,
list.elem[j+d[k]]=x;// 将list.elem[i]插入到正确位置
}
}
}
printf("希尔排序成功!结果如下:\n\n");
}
void adjustHeap(SqList &list,int s,int m)//堆调整
{
int x,j;
x=list.elem[s-1];//保存到x
for(j=2*s;j<=m;j*=2)
{
if(j<m&&list.elem[j-1]<list.elem[j+1-1])
{
j++;//j变为较大孩子的位置
}
if(x>list.elem[j-1]) //如果x比较大,则x应插入到位置s上
{
break;
}
list.elem[s-1]=list.elem[j-1];
s=j;
}
list.elem[s-1]=x;// 插入
}
void heapSort(SqList &list)//堆排序
{
int i,x;
for(i=list.length/2;i>0;i--)//将list.elem[0..list.length-1]建成大根堆
{
adjustHeap(list,i,list.length);
}
for(i=list.length;i>1;i--)
{
//将堆顶记录和未经排序的子序列list.elem[0..i-1]中的最后一个元素交换
x=list.elem[0];
list.elem[0]=list.elem[i-1];
list.elem[i-1]=x;
adjustHeap(list,1,i-1);//将list.elem[0..i-1-1]重新调整为大根堆
}
printf("堆排序成功!结果如下:\n\n");
}
//矩阵转置
#include<stdio.h>
#include <stdlib.h>
#define maxSize 12500//假设非零元个数的最大值为12500
typedef struct{
int i,j; //该非零元素的行列下标(i,j>=1)
int e; //非零元的值
}Triple;
typedef struct{
Triple data[maxSize+1];//非零元三元组表,data[0]未使用
int mu,nu,tu; //矩阵的行数、列数和非零元的个数
}TSMatrix;
void creatMatrix(TSMatrix &M);//创建三元组顺序表存储的矩阵
void transMatrix(TSMatrix M,TSMatrix &T);//T为M转置后的矩阵
void Display(TSMatrix M);//显示矩阵
int main ()
{
TSMatrix M,T;//M,T分别为转置前后的矩阵
creatMatrix(M);
transMatrix(M,T);
printf("转置后的矩阵T:\n");//显示转置后的矩阵
Display(T);//显示T
system("pause");
return 0;
}
void Display(TSMatrix M)
{
int i;
printf("行下标\t列下标\t元素值\n");
for(i=1;i<=M.tu;i++)
{
printf("%d\t%d\t%d\n",M.data[i].i,M.data[i].j,M.data[i].e);
}
}
void creatMatrix(TSMatrix &M)//创建三元组顺序表存储的矩阵
{
printf("请输入矩阵的行数:");
scanf("%d",&M.mu);
printf("请输入矩阵的列数:");
scanf("%d",&M.nu);
printf("请输入矩阵中非零元素的个数:");
scanf("%d",&M.tu);
printf("请输入三元组顺序表存储的矩阵M的初始数据:\n (数据值不能是0,下标从1开始,也不能为0)\n");
int i;
for(i=1;i<=M.tu;i++)
{
printf("请输入第%d个元素的行下标:",i);
scanf("%d",&M.data[i].i);
printf("请输入第%d个元素的列下标:",i);
scanf("%d",&M.data[i].j);
printf("请输入第%d个元素数据值:",i);
scanf("%d",&M.data[i].e);
}
printf("矩阵初始化成功!\n");
Display(M);// 显示M
system("pause");
}
void transMatrix(TSMatrix M,TSMatrix &T)//T为M转置后的矩阵
{
T.mu=M.nu;
T.nu=M.mu;
T.tu=M.tu;
int i;
int X0Num[M.nu];//X0Num[col]保存M中第col列中非零元个数
int Position[M.nu];// Position[col]保存M中第col列的第一个非零元在 T.data中的序号
int newPosition;//保存M.data中每个元素的新位置
if(T.tu)//空矩阵无需转置
{
for(i=1;i<=M.nu;i++)
{
X0Num[i]=0;//数组初始化为零
}
for(i=1;i<=M.tu;i++)
{
X0Num[M.data[i].j]++;//求每列中非零元个数
}
Position[1]=1;//M中第一列第一个非零元序号必然是1
for(i=2;i<=M.nu;i++)
{
Position[i]=X0Num[i-1]+Position[i-1];
}
//开始快速转置
for(i=1;i<=M.tu;i++)
{
newPosition=Position[M.data[i].j]; //newPosition保存M.data中每个元素的新位置
//新位置等于它所在列的第一个元素的位置加上它的列下标减一
T.data[newPosition].i=M.data[i].j;
T.data[newPosition].j=M.data[i].i;
T.data[newPosition].e=M.data[i].e;
Position[M.data[i].j]++;//M中第j列有一个元素转置后,Position[M.data[i].j]要加一,以便于每次 newPosition=Position[M.data[i].j];后,newPosition就是M中元素新位置
}
}
}
实验一:顺序表的基本操作
一、实验一需要我们实现如下的要求:
1、实现顺序表建立显示;
2、实现顺序表插入;
3、实现顺序表查找(显示比较次数);
4、实现顺序表删除(显示移动次数);
5、实现顺序表排序(分别实现简单选择、快速,显示比较次数、移动次数);
6、实现顺序表的折半查找(显示比较次数);
7、编程实现一个顺序表的就地逆置,即利用原表的存储空间将顺序表逆置;
8、顺序表有序插入(显示比较次数、移动次数),
屏幕提示后,从键盘输入一个元素值,在经过排序的线性表中插入这个元素;
屏幕显示比较次数和移动次数,应有溢出判断和报告;
9、要求以较高的效率实现删除顺序表中元素值在x到y(x和y自定)之间的所有元素;
10、编程实现将两个非递减的顺序表进行合并,要求同样的数据元素只出现一次;
*11、编程实现顺序表的shell排序(步长为5,3,1);
*12、编程实现堆排序算法;
*13、利用三元组顺序表存储矩阵,实现矩阵的转置(请独立写程序实现)
其中1、2、3、4、5中的简单选择排序、7、8是完全由自己独立编写
剩余的5中的快速选择排序,6, 10,11,12,13参考了教学PPT或书本上的代码
9中无需排序就可进行的较高效率的删除参考了CSDN上的代码。
二、遇到的问题及其相关解决措施,独特做法
1、主函数中将choice改为int型,并且将getch()改为scanf("%d",&choice);,用户如果不小心输入了自己不想执行功能的序号,程序不会立即执行该功能,按下回车后才会执行,用户有重新输入的余地,也可以输入两位数的数字选择对应的功能了,不像原来的情况,输入了一个字符就会立即执行,用户都来不及反应
2、主函数中swtich结构中增加了default,当用户输入错误的数值时,有提示,并且可以返回主界面
3、进行初始化、排序、删除等操作后,程序都会立即将操作后的顺序表显示出来,方便用户及时看到变化
4、表为空时,排序、逆置、合并、删除、查找等没有意义,所以增加了提示并返回功能
5、实现功能“3、实现顺序表查找(显示比较次数)”时,顺序表中可能会出现重复元素,导致一般的查找不能全部找出,所以添加了全盘查找功能用户,系统默认只查找第一个与输入的数值相同的元素,如果找到了,就会提示是否全盘查找,而实现功能“6、实现顺序表的折半查找(显示比较次数);”和“4、实现顺序表删除(显示移动次数);”时,也会有可能出现重复元素,这里暂时没有很好地解决;
6、快速排序的比较次数和移动次数我不是很明白,然后在CSDN上看到了有计算的代码,再和学姐的实验报告的结果一对比,就终于明白了比较次数应该在循环体内算,而将轴枢元素归位并不算是移动;
7、对折半查找的比较次数不够清楚,参考PPT后,发现折半查找的比较次数是与一个元素比较一下就算一次,而不是代码中if语句的判断次数,并且与要查找的数值的大小有关
8、在实现功能“以较高的效率实现删除顺序表中元素值在x到y(x和y自定)之间的所有元素”时,想不通什么是较高效率,于是我去CSDN上搜索后,发现了无需进行排序,就能进行较高效率删除的算法
9、合并顺序表时,每个顺序表都可能出现重复元素,也有两个顺序表互相重复的情况,对此,使用了while循环避免了合并后初中重复,不论初始化的第一个顺序表是否已经有序,函数都会帮用户排序一下,确保顺序表非递减,
10、希尔排序、堆排序、矩阵转置的思想忘得差不多了,又重新复习了一下,基本上可以理解了
11、默认插入或逆置后顺序表都为无序,以方便有序(非递减)插入的条件判断
三、界面展示&过程说明
下面是程序的过程执行过程的界面(因为代码垄长,所以请老师移步到.cpp文件中查看):
最初的界面
- 初始化
- 显示:
- 单个插入(插到末尾)
- 查找(PS:重新初始化后再查找)
表中没有所输入的数值时
- 删除
删除前:
删除后:
表中没有要删除的数值时:
- 简单选择排序(PS:重新初始化后的数据)
排序前:
排序后:
- 快速排序(经过6之后,已经有序所以要重新初始化)
快排前:
快排后
:
- 折半查找(前提:排序后。PS:接着快速排序之后,没有重新初始化)
成功:
不成功:
- 就地逆置
逆置前:
逆置后:
- 有序插入(重新初始化后并且经过了排序):
插入前:
插入后:
11、删除一定区间内的数字
(1)接着10之后进行操作,此时,顺序表有序:
(2)重新初始化,在无序状态下删除
删除前:
删除后:
- 合并顺序表(重新初始化后,还需要再手动初始化一次):
(不论初始化的第一个顺序表是否已经有序,函数都会帮用户排序一下,确保顺序表非递减)
如果未初始化第一个顺序表就选了12
先选择1初始化
然后选择12根据提示操作
- 希尔排序(重新初始化)
排序前:
排序后:
- 堆排序:(重新初始化)
排序前:
排序后:
独立程序:矩形的转置
四、体会与心得
写程序需要耐心与细心,写完后要尽早测试程序是否达到要求,不然等到要使用的时候,发现了错误或不足,有需要去大量更改,这就太浪费时间了;
刚刚写时,不要总是想着优化用户体验,不然会浪费很多时间在这个上面,先把功能写好了,才会有优化的资本;
数据结构考试过后,之前复习记住的编程思想又忘记了,还需要不断编程实战来让自己更加理解并且记住。