王道书籍上顺序表的基本操作和课后部分习题
一:头文件的定义
#ifndef SQLIST_H #define SQLIST_H /** * @author Dawn * @date 2019年11月1日23:26:04 * @version 1.0 * 数据结构二轮复习之顺序表 */ #include<stdio.h> #include<stdlib.h> #include<time.h> #define MaxSize 50 #define InitSize 100 typedef int ElemType; //静态分配 总空间大小是定死了的 typedef struct { ElemType data[MaxSize];//顺序表的元素 int length; }SqList; //动态分配 typedef struct { ElemType *data;//指示动态分配数组的指针 int length; int capacity;//顺序表的容量 }SeqList; //==========================顺序表的基本操作============================== //1.顺序表的初始化 void InitList_Sq(SqList &L); //2.顺序表的插入 bool ListInsert(SqList &L, int i, ElemType e); //3.顺序表的删除 bool ListDelete(SqList &L,int i,ElemType &e); //4.顺序表的按值查找,放回元素的位序 int LocateElem(SqList L, ElemType e); //==========================课后习题============================== //1.删除顺序表中最小的元素,并由函数返回该最小值,删除的位置由顺序表的最后一个元素代替 ElemType Del_Min1(SqList &L); //2.顺序表逆置 void Reverse2(SqList &L); //3.删除顺序表中所有值为x的元素 void Del_X3(SqList &L, ElemType e); void Del_X32(SqList &L, ElemType x); //4.删除有序表中值在(s,t)之间的元素,不包括s和t bool Del_s_t4(SqList &L, ElemType s, ElemType t); //5.删除顺序表中值在[s,t],包括s和t。注意和上一题的不同是“不是有序的哦”.但是思路确和第三题的又相同 bool Delete_s_t5(SqList &L, ElemType s, ElemType t); //6.删除有序顺表中的重复的元素,使所有元素均不相同 比如1 2 2 2 4 5 =======》 1 2 4 5 bool Delete_Same6(SqList &L); void Delete_Same62(SqList &L); //7.将2个有序表的合并 bool Merge7(SqList A, SqList B, SqList &C); //8.数组左部分元素和右部分元素进行换位子,[123 | 456] => [456 | 123] void Reverse8(int arr[], int left, int right, int arraySize); void Exchange8(int arr[], int m, int n, int arraySize); //9.二分法查找元素,如果查找成功,则将该元素与他的后继元素交换,查找不成功就将该元素的插入到正确位置,使之有序 void BSearchE9(int arr[],int length, ElemType e); //10.跑步机的感觉,比如数组 1,2,3,4,5,6,7总的容量不变的情况下,左右2(p)个位置,变成 6,7,1,2,3,4,5 void Reverse10(int arr[], int left, int right); void Exchange10(int arr[], int p, int length); //==========================广大915真题篇============================== //2019第一题,1。生成一个长度为20的顺序表,2。元素值随机在100直接,3。将元素值小于50的放在前一部分 void Exchange(SqList &L); //==========================常用函数============================== int CreatRandom(); void PrintSqlist(SqList L); void PrintArray(int arr[]); #endif // !SQLIST_H
二:具体的实现
#include"SqList.h" //==========================顺序表的基本操作============================== //1.初始化顺序表 可以改成有序和无序的2种 void InitList_Sq(SqList &L) {//静态数组的初始化 //1 固定有序的数组 1,2,3,4,5 ||或者固定无序的数组 2 for (int i = 0; i < 5; i++) { L.data[i] = i + 1; } //用来生成有序且中间有重复的顺序表 1 2 2 4 5 L.data[2] = 2; //2 随机0-9的数组 //srand(time(NULL));//使用时间当做随机数种子 //for (int i = 0; i < 5; i++) { // //L.data[i] = CreatRandom(); // L.data[i] = rand() % 10; //} //3 固定的数组 2 1 5 3 4 //L.data[0] = 2; //L.data[1] = 1; //L.data[2] = 5; //L.data[3] = 2; //L.data[4] = 4; L.length = 5;//长度为 5 } //2.顺序表的插入(元素前插) bool ListInsert(SqList &L, int i, ElemType e) { //step1:判断插入的位置是否合理,(这里的i代表的是逻辑结构) if (i<1 || i>L.length + 1) return false; if (L.length >= MaxSize)//存储空间已经满了 return false; //step2:正式插入,将第个元素及以后的元素整体后移一位 for (int j = L.length; j >= i; j--) L.data[j] = L.data[j - 1]; //执行(length-i)次 L.data[i - 1] = e; L.length++;//长度++ return true; } //3.顺序表的删除 bool ListDelete(SqList &L, int i, ElemType &e){ //判断删除元素位置是否合理 if (i<1 || i>L.length) return false; e = L.data[i - 1];//将删除元素赋值给e //将第i个位置后的元素前移 for (int j = i; j < L.length; j++) { L.data[j - 1] = L.data[j]; } L.length--; return true; } //4.顺序表的按值查找,放回元素的位序 int LocateElem(SqList L, ElemType e) { int i; for (i = 0; i < L.length; i++) { if (L.data[i] == e) { return i + 1; } } return 0; } //==========================课后习题============================== //1.删除顺序表中最小的元素,并由函数返回该最小值,删除的位置由顺序表的最后一个元素代替 ElemType Del_Min1(SqList &L) { //表空就返回 if (L.length == 0) return 999; int min = L.data[0];//假设第一个元素为最小 int pos = 0;//最小值的位置 //循环查找到最小值 for (int i = 0; i < L.length; i++) { if (L.data[i] < min) { min = L.data[i]; pos = i; } } //找到了最小值,最后一个元素的值赋给最小值的位置 L.data[pos] = L.data[L.length - 1]; L.length--; return min;//返回最小值 } //2.顺序表逆置 void Reverse2(SqList &L) { ElemType temp; for (int i = 0; i < L.length / 2; i++) { temp = L.data[i]; L.data[i] = L.data[L.length - i - 1]; L.data[L.length - i - 1] = temp; } } //3.删除顺序表中所有值为x的元素 //方法一:用k记录等于x的元素的个数,如果遇到值为x的元素,就k++,如果遇到的元素值不是x,就前移k个位置 void Del_X3(SqList &L, ElemType x) { int k = 0, i = 0; while (i < L.length) { if (L.data[i] == x) k++; else L.data[i - k] = L.data[i]; i++; } L.length -= k; } //方法二:用k记录不等于x的元素,将不等于x的元素向前移动k个位置 void Del_X32(SqList &L, ElemType x) { int k = 0; for (int i = 0; i < L.length; i++) { if (L.data[i] != x) { L.data[k] = L.data[i]; k++; } } L.length = k; } //4.删除有序表中值在(s,t)之间的元素,不包括s和t //思路:找到值大于等于s的第一个元素(第一个删除的元素),然后再找值大于t的第一个元素(最后一个删除元素的下一个元素。因为t的值有可能在顺序表中没有) bool Del_s_t4(SqList &L, ElemType s, ElemType t) { int i, j; //判断s t是否输入正确 if (s >= t || L.length == 0) return false; //寻找大于s的第一个数 for (i = 0; i < L.length && L.data[i] <= s; i++) ;//这样写有点装逼。 哈哈哈 if (i >= L.length) return false;//所有元素均小于s //寻找第一个大于t的下一个数 for (j = i; j < L.length && L.data[j] < t; j++); //前移填补被删除的元素 for (; j < L.length; j++, i++) L.data[i] = L.data[j]; L.length = i; return true; } //5.删除顺序表中值在[s,t],包括s和t。注意和上一题的不同是“不是有序的哦”.但是思路确和第三题的又相同 bool Delete_s_t5(SqList &L, ElemType s, ElemType t) { int k=0;//记录符合条件的元素 if (L.length == 0 && s >= t) return false; for (int i = 0; i < L.length; i++) { if (L.data[i] >= s && L.data[i] <= t) k++; //如果值是在[s,t]中的,就k else L.data[i - k] = L.data[i]; } L.length -= k; return true; } //6.删除有序顺表中的重复的元素,使所有元素均不相同 比如1 2 2 2 4 5 =======》 1 2 4 5 //思路:有点类似直接插入排序的思想,初始时将第一个看成非重复的有序表。 // 之后一次判断后面的元素是否与前面非重复的有序表的最后的一个元素是否相同,如果相同,则继续向后判断。如果不同,则插入到非重复元素的最后,直到判断结束 bool Delete_Same6(SqList &L) { //使用2个游标来操作顺序表,j用来真正的遍历,i用来记录非重复元素的最后一个位置 int i, j; if (L.length == 0) return false; for (i = 0, j = 1; j < L.length; j++) if (L.data[i] != L.data[j])//如果不同,则插入到非重复元素的最后,直到判断结束 L.data[++i] = L.data[j]; L.length = i + 1; return true; } //删除无序顺表中的重复的元素?又该怎么操作了...不是很熟悉,这个呀呀呀 void Delete_Same62(SqList &L) { int i, j = 0, k;//k是非重复元素区间中的游标 for (i = 1; i < L.length; i++) { k = 0; while (k <= j && L.data[k] != L.data[i]) k++;//在非重复的区间中看是否与第i个元素相同。如果没有的话k>j if (k > j) L.data[++j] = L.data[i]; } L.length = j + 1; } //7.将2个有序表的合并 bool Merge7(SqList A, SqList B, SqList &C) { //step1:判断C的容量大小是否正确 if (A.length + B.length > MaxSize)//这里的MaxSize是指C的最大值 return false; int i = 0, j = 0, k = 0;//分别是A B C的工作游标 //step2:twotwo比较A B中较小的元素存入C中 while (i < A.length&&j < B.length) { if (A.data[i] < B.data[j]) C.data[k++] = A.data[i++];//A中较小的的元素放在C中了 else C.data[k++] = A.data[j++];//A中较小的的元素放在C中了 } //step3:A B中必有一个空余,将剩下的元素全部存在C中 while (i < A.length) C.data[k++] = A.data[i++]; while (j < B.length) C.data[k++] = B.data[j++]; C.length = k; return true; } //8.数组左部分元素和右部分元素进行换位子,[123 | 456] => [456 | 123] void Reverse8(int arr[], int left, int right, int arrayLen) { //将一个数组指定一部分进行逆置,和第二题写的逆置有点区别,细品 if (left >= right && right >= arrayLen) return;//传入的参数不合理 int mid = (left + right) / 2; for (int i = 0; i <= mid - left; i++) { int temp = arr[left + i];// arr[left + i] = arr[right - i]; arr[right - i] = temp; } } void Exchange8(int arr[], int m, int n, int arraySize) { Reverse8(arr, 0, m + n - 1, arraySize); Reverse8(arr, 0, n - 1, arraySize); Reverse8(arr, n, m + n - 1, arraySize); } //9.二分法查找元素,如果查找成功,则将该元素与他的后继元素交换,查找不成功就将该元素的插入到正确位置,使之有序 void BSearchE9(int arr[],int length,ElemType x) { int low = 0, high = length - 1, mid; int i; while (low <= high) { mid = (high - low) / 2; if (arr[mid] == x) break; else if (arr[mid] < x) low = mid + 1; else high = mid - 1; } //找到了元素,但是如果找到的是最后一个元素就不需要进行交换 if (arr[mid] == x && mid != length - 1) { int temp = arr[mid]; arr[mid] = arr[mid + 1]; arr[mid + 1] = temp; } //如果没有找到和x相等的元素,在high的后面上插入x if (low > high) { for (i = length - 1; i > high; i--) { arr[i + 1] = arr[i];//后移元素,为插入做好准备 } arr[i + 1] = x;//插入x } } //10.跑步机的感觉,比如数组 1,2,3,4,5,6,7总的容量不变的情况下,左右2(p)个位置,变成 6,7,1,2,3,4,5 //思路:和第8题有点类似,先将整个数组逆置,得到7654321 再逆置0-p的位置的元素,再将p-7的元素逆置 void Reverse10(int arr[], int left, int right) { int i, temp; int mid = (right - left) / 2; for (i = 0; i <= mid; i++) { temp = arr[left+i]; arr[left+i] = arr[right - i]; arr[right - i] = temp; } } void Exchange10(int arr[], int p, int length) { Reverse10(arr, 0, length - 1); Reverse10(arr, 0, p - 1);//p为偏移量 Reverse10(arr, p, length - 1);//p为偏移量 } //11.求2个等长的有序序列拼在一起的中位数,比如序列A: 11,13,15,17,19的中位数为15。 序列B:2,4,6,8,20的中位数位6。AB的中位数为 11 //思路:1:当中位数a==b时,a或者b就是中位数: // 2:当a<b时,舍弃A中较小的一半,同时舍弃B中较大的一半 // 3:当a>b时,舍弃A中较大的一半,同时舍弃B中较小的一半 A:11,13,15 B:6,8,20 ==> A:11,13 B:8,20 ==>A:11 B:20(当是偶数时删除B的中间点,不删除A的中间点) //恶心代码不写了。。。。。。。。。。。。 //==========================915真题篇============================== //2019第一题,要求:step1:生成一个长度为20的顺序表,2:元素值是随机在0-100之间,3:将元素值小于50的放在前一部分 //思路:将数组看成小于50的区间(L1),和大于50的区间(R2),进行遍历整个数组,判断每个元素是是否小于50, // 如果元素小于50的话,就和元素小于50的那个区间(L1)的最后一个元素交换 void Exchange(SqList &L) { int i, k = 0;//k为要进行交换的元素 //初始化,创建20个在(0,100)之间的的随机数 srand(time(NULL));//使用时间当做随机数种子 for (i = 0; i < 20; i++) { L.data[i] = rand() % 100; } L.length = 20; for (i = 0; i < L.length; i++) if (L.data[i] < 50) {//如果元素小于50,就和小于50的区间段的最后一个元素交换 int temp = L.data[k]; L.data[k++] = L.data[i]; L.data[i] = temp; } } //==========================常用函数============================== //生成随机数 int CreatRandom() { srand(time(NULL));//使用时间当做随机数种子 return rand() % 10;//生成0-9的随机数 } //打印顺序表 void PrintSqlist(SqList L) { for (int i = 0; i < L.length; i++) { printf("%d ,", L.data[i]); } printf(" "); } //打印数组 void PrintArray(int arr[]) { int i = 0; while (i < 6) { printf("%d ,", arr[i++]); } printf(" "); }
三:主函数如下
需注意在测试的时候记得更改顺序表中初始化的部分代码,看是需要随机数组还是有序数组等等。。。。
#include"SqList.h" int main() { SqList L; int e, temp; int arr[6] = {1,2,3,4,5,6}; InitList_Sq(L); //----------顺序表的基本操作-------------- //顺序表的插入 //ListInsert(L, 2, 8); //顺序表的删除 //ListDelete(L, 1, e); //printf("删除的元素为:%d", e); //顺序表的按值查找 //temp=LocateElem(L, 3); //printf("元素--3--在的位置为:%d ",temp); //----------课后习题---------------------- //1.删除顺序表中最小的元素,并由函数返回该最小值,删除的位置由顺序表的最后一个元素代替 //temp = Del_Min1(L); //printf("删除的最小值为:%d ", temp); //2.顺序表逆置 //Reverse2(L); //3.删除顺序表中所有值为x的元素 //Del_X3(L, 2); //Del_X32(L, 2); //4.删除有序表中值在(s,t)之间的元素,不包括s和t //Del_s_t(L, 1, 5); //5.删除顺序表中值在[s,t],包括s和t。注意和上一题的不同是“不是有序的哦”.但是思路确和第三题的又相同 //Delete_s_t5(L, 2, 5); //6.删除有序顺表中的重复的元素,拿有序表测试 使所有元素均不相同 比如1 2 2 2 4 5 =======》 1 2 4 5 //Delete_Same6(L); //Delete_Same62(L); //7.将2个有序表的合并 //Merge7(L, L, L);//A,B,C //8.数组左部分元素和右部分元素进行换位子,[123 | 456] => [456 | 123] //Exchange8(arr, 3, 3, 6); //PrintArray(arr); //9.二分法查找元素,如果查找成功,则将该元素与他的后继元素交换,查找不成功就将该元素的插入到正确位置,使之有序 //BSearchE9(arr, 6, 3); //PrintArray(arr); //10.跑步机的感觉,比如数组 1,2,3,4,5,6,7总的容量不变的情况下,左右2(p)个位置,变成 6,7,1,2,3,4,5 //Exchange10(arr, 3, 6); //PrintArray(arr); //------------真题测试---------------- //Exchange(L); PrintSqlist(L); system("pause"); return 0; }