远古课程作业 数据结构与算法实习 顺序表的基本操作 (附源码和实验报告,95分以上,做法不一定全对)

/*
	源文件名: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文件中查看):

最初的界面

  1. 初始化

  1. 显示:

  1. 单个插入(插到末尾)

  1. 查找(PS:重新初始化后再查找)

表中没有所输入的数值时

  1. 删除

删除前:

删除后:

表中没有要删除的数值时:

  1. 简单选择排序(PS:重新初始化后的数据)

排序前:

排序后:

  1. 快速排序(经过6之后,已经有序所以要重新初始化)

快排前:

快排后

  1. 折半查找(前提:排序后。PS:接着快速排序之后,没有重新初始化)

成功:

不成功:

  1. 就地逆置

逆置前:

逆置后:

  1. 有序插入(重新初始化后并且经过了排序):

插入前:

插入后:

11、删除一定区间内的数字

(1)接着10之后进行操作,此时,顺序表有序:

(2)重新初始化,在无序状态下删除

删除前:

删除后:

  1. 合并顺序表(重新初始化后,还需要再手动初始化一次):

(不论初始化的第一个顺序表是否已经有序,函数都会帮用户排序一下,确保顺序表非递减)

如果未初始化第一个顺序表就选了12

先选择1初始化

然后选择12根据提示操作

  1. 希尔排序(重新初始化)

排序前:

排序后:

  1. 堆排序:(重新初始化)

排序前:

排序后:

独立程序:矩形的转置

四、体会与心得

写程序需要耐心与细心,写完后要尽早测试程序是否达到要求,不然等到要使用的时候,发现了错误或不足,有需要去大量更改,这就太浪费时间了;

刚刚写时,不要总是想着优化用户体验,不然会浪费很多时间在这个上面,先把功能写好了,才会有优化的资本;

数据结构考试过后,之前复习记住的编程思想又忘记了,还需要不断编程实战来让自己更加理解并且记住。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值