一、实验目的:
1、各种排序算法的实现
2、各种查找算法实现
二、使用仪器、器材
微机一台
操作系统:WinXP
编程软件:C++
三、实验内容及原理
实验内容:
1、各种排序算法的实现
用随机函数生成16个2位正整数(10~99),实现插入排序、选择排序、冒泡排序、双向冒泡、快速排序、二路归并排序等多种排序算法,输出排序中间过程、统计关键字的比较次数和记录的移动次数。
(1)顺序查找:使用数组或链表结构。用随机函数生成16个不重复的字母(’a’~’z’),键盘输入待查找的字母,返回查找成功与否,若成功则返回该字母所在的位置(序号),并计算比较次数。
(2)折半查找:用数组实现,查找前元素先排序。计算比较次数。分别用查找成功、不成功进行测试。
(3)二叉查找树:手工输入10个字母,生成一棵二叉查找树,用递归算法打印树结构或分别输出先序和中序遍历序列以确认其结构。键盘输入待查找的字母,计算比较次数。分别用查找成功、不成功进行测试。
#include
#include
using namespace std;
const int num = 100;
struct sqlist
{
int l[num];
int length;
};
//插入排序
//通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
void InsertSort(sqlist list)
{
int compare = 0;//关键字比较次数
int remove = 0;//关键字移动次数
int process = 1;//中间过程
for (int i = 2;i <= list.length;i++)
{
compare++;
if (list.l[i]< list.l[i-1])
{
list.l[0] = list.l[i];//设置哨兵
list.l[i] = list.l[i - 1];
int j = 0;
for (j = i - 2;list.l[0] < list.l[j];j--)
{
list.l[j + 1] = list.l[j];//依次右移
}
list.l[j + 1] = list.l[0];//将哨兵插入合适的位置
remove++;
}
//输出中间过程
cout << "第" << process++ << "次中间过程输出:" << endl;
for (int i = 1;i <= list.length;i++)
{
cout << list.l[i] << " ";
}
cout << endl;
}
//输出关键字比较次数和关键字移动次数
cout << "关键字【比较】次数:" << compare << endl;
cout << "关键字【移动】次数:" << remove << endl;
}
//选择排序
//首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
//再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
//重复第二步,直到所有元素均排序完毕。
void SelectSort(sqlist list)
{
int k = 0;
int compare = 0;//关键字比较次数
int remove = 0;//关键字移动次数
int process = 1;//中间过程
for (int i = 1;i < list.length;i++)
{
k = i;
for (int j = i+1;j <= list.length;j++)
{
compare++;
if (list.l[j] < list.l[k])
{
k = j;//k:此趟排序中关键字最小记录
}
}
if (k != i)//交换l[i]和l[k]
{
remove++;
int temp = list.l[i];
list.l[i] = list.l[k];
list.l[k] = temp;
//输出中间过程
cout << "第" << process++ << "次中间过程输出:" << endl;
for (int i = 1;i <= list.length;i++)
{
cout << list.l[i] << " ";
}
cout << endl;
}
}
//输出关键字比较次数和关键字移动次数
cout << "关键字【比较】次数:" << compare << endl;
cout << "关键字【移动】次数:" << remove << endl;
}
//冒泡排序
//比较相邻的元素。如果第一个比第二个大,就交换他们两个。
//对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
//针对所有的元素重复以上的步骤,除了最后一个。
void BubbleSort(sqlist list)
{
int compare = 0;//关键字比较次数
int remove = 0;//关键字移动次数
int process = 1;//中间过程
int m = list.length - 1;
int flag = 1;//用于标记某一趟排序是否发生交换
while (1)
{
flag = 0;//若本趟没有发生交换则结束排序
for (int i = 0;i <= m;i++)
{
compare++;
if (list.l[i] > list.l[i + 1])
{
flag = 1;
int temp = list.l[i + 1];
list.l[i + 1] = list.l[i];
list.l[i] = temp;
remove++;
}
}
if (flag == 0)
{
break;
}
//输出中间过程
cout << "第" << process++ << "次中间过程输出:" << endl;
for (int i = 1;i <= list.length;i++)
{
cout << list.l[i] << " ";
}
cout << endl;
--m;
}
//输出关键字比较次数和关键字移动次数
cout << "关键字【比较】次数:" << compare << endl;
cout << "关键字【移动】次数:" << remove << endl;
}
//双向冒泡排序
//首先从前往后把最大数移到最后,然后反过来从后往前把最小的一个数移动到数组最前面,
//这一过程就是第一轮,然后重复这一过程,最终就会把整个数组从小到大排列好。
void TwowaybubbleSort(sqlist list)
{
int compare = 0;//关键字比较次数
int remove = 0;//关键字移动次数
int process = 1;//中间过程
int flag = 1;
int n = list.length;
int left = 1;
int right = list.length;
int templeft = 0;
int tempright = 0;
while (1)
{
flag = 0;
for (int j = left;j < right;j++)
{
compare++;
if (list.l[j] > list.l[j + 1])
{
flag = 1;
remove++;
int temp = list.l[j];
list.l[j] = list.l[j + 1];
list.l[j + 1] = temp;
tempright = j;
}
}
right = tempright;
for (int j = right;j > left;j--)
{
compare++;
if (list.l[j] < list.l[j - 1])
{
flag = 1;
remove++;
int temp = list.l[j];
list.l[j] = list.l[j - 1];
list.l[j - 1] = temp;
templeft = j;
}
}
left = templeft;
if (flag == 0)
{
break;
}
//输出中间过程
cout << "第" << process++ << "次中间过程输出:" << endl;
for (int i = 1;i <= list.length;i++)
{
cout << list.l[i] << " ";
}
cout << endl;
}
//输出关键字比较次数和关键字移动次数
cout << "关键字【比较】次数:" << compare << endl;
cout << "关键字【移动】次数:" << remove << endl;
}
//快速排序
//从数列中挑出一个元素,称为 "基准"(pivot);
//重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。
//在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
//递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;
int Qcompare = 0;//关键字比较次数
int Qremove = 0;//关键字移动次数
int Qprocess = 1;//中间过程
void QuickSort(sqlist list, int low, int high)
{
int i, j, pivotkey;
i = low;
j = high;
if (low < high)
{
pivotkey = list.l[low];
while (i != j)
{
while (j > i && list.l[j]>=pivotkey)
{
j--;
Qcompare++;
}
if (i < j)
{
list.l[i] = list.l[j];
i++;
Qremove++;
}
while (i < j && list.l[i] <= pivotkey)
{
i++;
Qcompare++;
}
if (i < j)
{
list.l[j] = list.l[i];
j--;
Qremove++;
}
}
list.l[i] = pivotkey;
//输出中间过程
cout << "第" << Qprocess++ << "次中间过程输出:" << endl;
for (int i = 1;i <= list.length;i++)
{
cout << list.l[i] << " ";
}
cout << endl;
QuickSort(list, low, i - 1);
QuickSort(list, i+1, high);
}
}
//二路归并排序
//申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
//设定两个指针,最初位置分别为两个已经排序序列的起始位置;
//比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
//重复步骤 3 直到某一指针达到序列尾;
//将另一序列剩下的所有元素直接复制到合并序列尾。
int Mcompare = 0;//关键字比较次数
int Mremove = 0;//关键字移动次数
int Mprocess = 1;//中间过程
void Merge(sqlist &list,int low,int mid,int high)//相邻两个有序子序列的归并
{
int len = high - low + 1;
int* temp = new int[len];
int i = low;
int j = mid + 1; //i,j为两个子序列的下标
int k = 0; //新合并的数组的下标
while (i <= mid && j <= high)
{
if (list.l[i] <= list.l[j])
{
Mcompare++;
Mremove++;
temp[k] = list.l[i];
i++;
k++;
}
else
{
Mcompare++;
Mremove++;
temp[k] = list.l[j];
j++;
k++;
}
}
while (i <= mid)
{
temp[k] = list.l[i];
i++;
k++;
}
while (j <= high)
{
temp[k] = list.l[j];
j++;
k++;
}
for (int i = 0;i < len;i++)
{
list.l[low + i] = temp[i];
}
}
void MergeSort(sqlist &list, int low, int high)
{
if (low < high)
{
int mid = (low + high) / 2;
MergeSort(list, low, mid);
MergeSort(list, mid + 1, high);
Merge(list, low, mid, high);//合并左右序列
}
//输出中间过程
cout << "第" << Mprocess++ << "次中间过程输出:" << endl;
for (int i = 1;i <= list.length;i++)
{
cout << list.l[i] << " ";
}
cout << endl;
}
int main()
{
sqlist list;
cout << "请输入数组的长度:";
cin >> list.length;
cout << "随机生成的长度为" << list.length << "的数组为:" << endl;
srand(time(0));
for (int i = 1;i <= list.length;i++)
{
list.l[i] = rand() % 90 + 10;
cout << list.l[i] << " ";
}
cout << endl;
cout << "------------【插入排序】------------" << endl;
InsertSort(list);
cout << "------------【选择排序】------------" << endl;
SelectSort(list);
cout << "------------【冒泡排序】------------" << endl;
BubbleSort(list);
cout << "------------【双向冒泡排序】------------" << endl;
TwowaybubbleSort(list);
cout << "------------【快速排序】------------" << endl;
QuickSort(list,1,list.length);
//输出关键字比较次数和关键字移动次数
cout << "关键字【比较】次数:" << Qcompare << endl;
cout << "关键字【移动】次数:" << Qremove << endl;
cout << "------------【二路归并排序】------------" << endl;
MergeSort(list, 1, list.length);
cout << "关键字【比较】次数:" << Mcompare << endl;
cout << "关键字【移动】次数:" << Mremove << endl;
}
#include
#include
using namespace std;
//-----顺序查找-----
void SeqSearch(char* s)
{
cout << "请输入想寻找的字母:";
char x;
cin >> x; //输入想找的字母
int index = 0;
int count = 0; //比较次数,初始化为0
int flag = 0;
while (count<16)
{
++count;
if (s[index++] == x)
{
cout << "已找到字母 " << x << " ,它的下标为:" << index - 1 << endl;
flag = 1;
break;
}
}
if (flag==0)
{
cout << "没有找到该字母,共比较了" << count << " 次" << endl;
}
else cout << "一共比较了" << count << " 次"<> x; //输入待寻找的字母
int compare = 0; //记录比较次数
int low = 0; int high = 15;
int mid = 0;
while (low <= high) {
mid = (low + high) / 2;
if (x == s[mid])
{
compare++;
cout << "已找到字母 " << x << ",它的下标为:" << mid << endl;
break;
}
else if (x < s[mid]) {
compare++;
high = mid - 1;
}
else {
compare++;
low = mid + 1;
}
}
if (low > high && x != s[low]) cout << "未找到该字母,总共比较了 " << compare << " 次" << endl;
else cout << "一共比较了 " << compare << " 次" << endl;
}
//-----二叉查找树-----
struct Node
{
char data;
struct Node* left;
struct Node* right;
};
void preorder(Node* root)//先序遍历递归
{
if (root != NULL)
{
cout << root->data << " ";
preorder(root->left);
preorder(root->right);
}
}
void inorder(Node* root)//中序遍历递归
{
if (root != NULL)
{
inorder(root->left);
cout << root->data << " ";
inorder(root->right);
}
}
void insert(Node*&head, char c)
{
if (!head)
{
Node* s = new Node;
s->data = c;
s->left = s->right = NULL;
head = s;
}
else if (c < head->data)
{
insert(head->left, c);
}
else if (c > head->data)
{
insert(head->right, c);
}
}
int BSTcompare = 0;
void SearchBST(Node* head, char c)//查找
{
BSTcompare++;
if (!head || c == head->data)
{
if (!head)
{
cout << "查找失败,共查找了" << BSTcompare << "次" << endl;
}
else
{
cout << "已找到字母" << c << ",共查找了" << BSTcompare << "次" << endl;
}
}
else if (c < head->data) SearchBST(head->left, c);
else if (c >= head->data) SearchBST(head->right, c);
}
int main()
{
//生成随机数组
srand(unsigned(time));
char* c = new char[16];
for (int i = 0; i < 16; i++) c[i] = '\0';
cout << "生成的数组为:";
int k = 0;
while (k != 16) {
int flag = 0; //检测是否有相同的字母出现
c[k] = 'a' + (rand() % 26);
for (int i = 0; i < 16; i++) {
if (k != i) {
if (c[k] == c[i]) flag = 1; //若flag=1,则重新加入随机一个字母
}
}
if (flag == 0) ++k; //若flag=0,往数组下一个位置添加字母
}
for (int i = 0; i < 16; i++)
{
cout << c[i] << " ";
}
cout << endl;
cout << "-----顺序查找-----" << endl;
SeqSearch(c);
cout << endl;
cout << "-----折半查找-----" << endl;
BinSearch(c);
cout << "------二叉查找树-----" << endl;
Node* root = NULL;
Node* Root = NULL;
cout << "请输入十个字母:" << endl;
char C;
cout << "请输入第" <<1 << "个字母:";
cin >> C;
insert(root, C);
for (int i = 1;i < 10;i++)
{
Root = root;
char c;
cout << "请输入第" << i + 1 << "个字母:";
cin >> c;
insert(root, c);
}
cout << "先序遍历:" << endl;
preorder(root);cout << endl;
cout << "---------------------------" << endl;
cout << "中序遍历:" << endl;
inorder(root);cout << endl;
char letter=' ';
cout << "请输入你想要查找的字母:";
cin >> letter;
SearchBST(root, letter);
}