笔者近日在学习数据结构(基于严蔚敏版数据结构教材),在学习过程中也出现了不少问题和解决问题之后的一些感悟。
顺序表又称顺序存储结构,是线性表的一种,专门存储逻辑关系为“一对一”的数据。
顺序表存储数据的具体实现方案是:将数据全部存储到一整块内存空间中,数据元素之间按照次序挨个存放。
下面将主要介绍顺序表的实现,附带查找中间数函数代码实现,以及基于顺序表的快速排序算法实现。
问题描述如下:
/*
1)在一个整数序列a1,a2,…,an中,若存在一个数,大于它的整数数量和小于它的整数数量相等,则该数被称为“中间数”。请编写程序实现整数序列的“中间数”测试。具体样例:
/*样例输入 5 //包含5个整数的序列
3 4 6 6 7 //随机产生一个整数序列
则输出
-1 //输出-1表示整数序列“3 4 6 6 7”中不存在中间数
说明:
①在一个整数序列中,可能存在多个中间数。
②整数序列在程序中由随机数生成,程序输出“中间数”的值,若中间数不存在,则输出-1。*/
代码实现如下:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define MaxSize 1000
//结构体定义
typedef struct {
int* data;//存储空间基地址
int length;
}Sqlist;
//主要函数声明
void InitList(Sqlist* L);//初始化顺序表
void CreateList(Sqlist* L, int n);//创建随机数顺序表
void PrintList_1(Sqlist* L);//打印随机顺序表中的元素
void PrintList_2(Sqlist* L);//打印排序顺序表中的元素
void insertList(Sqlist* L, int n, int m);//向顺序表指定位置插入元素
void deleteList(Sqlist* L, int n);//删除顺序表指定位置的元素
void bubble_SortList(Sqlist* L);//冒泡排序,对顺序表元素进行排序
int partition(Sqlist* L, int left, int right);//递归实现快速排序
void quick_SortList(Sqlist* L, int left, int right);//快速排序,时间复杂度小
int Search_mid_num(Sqlist* L);//寻找中间数
void mid_num_game();//游戏主页面
//初始化顺序表,创建一个空表
void InitList(Sqlist* L)
{
L->data = (int*)malloc(MaxSize*sizeof(int));
//申请一块动态存储空间
if (!L->data) {
printf("存储空间分配失败!");
}
L->length = 0;//初始化顺序表长度为0;
}
//创建指定大小的顺序表
void CreateSqlist(Sqlist* L, int n)
{
int i = 0;
srand((unsigned)time(NULL));//修改随机数种子
for (i = 0; i < n; i++) {
L->data[i] = (int)rand()%101;
L->length++;
}
}
//打印随机数顺序表
void PrintSqlist_1(Sqlist* L)
{
int i;
printf("打印出随机数顺序表为:\n");
printf("*********************\n");
for (i = 0; i < L->length; i++) {
printf("%d ", L->data[i]);
}
printf("\n*********************\n");
}
//打印排序后的顺序表
void PrintSqlist_2(Sqlist* L)
{
int i;
printf("打印排序后的顺序表为:\n");
printf("*********************\n");
for (i = 0; i < L->length; i++) {
printf("%d ", L->data[i]);
}
printf("\n*********************\n");
}
//删除指定位置的元素
void DeleteSqlist(Sqlist* L, int n)
{
int i = 0;
if (n > L->length || n < 1) {
printf("删除位置非法!\n");
}
else {
for (i = n; i < L->length; i++) {
L->data[i - 1] = L->data[i];
}
L->length--;
}
}
//在指定位置插入元素
insertSqlist(Sqlist* L, int n, int m) //n是插入元素的位置,m是插入元素的大小
{
if (n > L->length + 1||n < 1) {
printf("插入位置非法!");
}
else {
int i = 0;
for (i = L->length - 1; i >= n - 1; i--) {
L->data[i + 1] = L->data[i];
//从后往前交换,防止值被覆盖
}
L->data[n - 1] = m;//将要插入的元素放在指定位置
L->length++;//将顺序表长度+1
}
}
//冒泡排序实现
void SortList(Sqlist* L)
{
int i = 0;//第几趟冒泡排序
for (i = 0; i < L->length; i++) {
int j = 0;
for (j = 0; j < L->length - 1 - i; j++) {
int tmp;
if (L->data[j] > L->data[j + 1]) {
tmp = L->data[j + 1];
L->data[j + 1] = L->data[j];
L->data[j] = tmp;
}
}
}
}
//寻找中间数,此算法遍历整个顺序表中的元素(时间复杂度较大),不用排序也可实现。
int Search_mid_num(Sqlist* L)
{
int i = 0;
for (i = 0; i < L->length - 1; i++) {
int j = 0;
int count_little = 0;
int count_big = 0;
for (j = 0; j < L->length; j++) {
if (L->data[i] > L->data[j]) {
count_little++;
}
else if (L->data[i] < L->data[j]) {
count_big++;
}
else {
;
}
}
if (count_little == count_big) {
return (L->data[i]);
}
else {
;
}
/*printf("count_little = %d\n", count_little);
printf("count_big = %d\n", count_big);*/
}
return -1;
}
//partition函数实现,函数返回值是元素下标
int partition(Sqlist* L, int left, int right)
{
int tmp = L->data[left];
while (left < right) {
while (left < right && L->data[right] >= tmp) {
right--;
}
L->data[left] = L->data[right];
while (left < right && L->data[left] <= tmp) {
left++;
}
L->data[right] = L->data[left];
}
L->data[left] = tmp;
return left;
}
//快速排序实现
void quick_SortList(Sqlist* L, int left, int right)
{
if (left < right) {
int mid = partition(L, left , right);
quick_SortList(L, left, mid - 1);
quick_SortList(L, mid + 1, right);
}
}
//游戏主页面
void mid_num_game()
{
Sqlist L;
int len;
printf("请输入数列的长度>");
scanf("%d", &len);
InitList(&L);
CreateSqlist(&L, len);
PrintSqlist_1(&L);
quick_SortList(&L, 0, len - 1);
PrintSqlist_2(&L);
//若是排序后,可以直接返回中间数,不用使用查找函数
int flag = Search_mid_num(&L);
if (flag == -1) {
printf("\n此随机数组没有中间数!");
}
else {
printf("\n随机数组中的中间数是%d", flag);
}
}
int main(void)
{
mid_num_game();
return 0;
}