线性表
1.
#include <stdio.h> //标准输入输出头文件
#include <stdlib.h> //standard library标准库头文件 ,包含了C、C++语言的最常用的系统函数。
void delete(int *arr, int len){
if(!len){
printf("数组为空");
return;
}
int min = *arr, minpos = 0;
for(int i = 0; i < len; i++){
if(min > *(arr + i)){
min = *(arr + i);
minpos = i;
}
}
//找到最小值后,将最后一个元素补到删除位置
*(arr + minpos) = *(arr + len - 1);
*(arr + len - 1) = NULL;
}
int main()
{
int n; //数组元素个数
printf("输入数组元素个数n= ");
scanf("%d", &n);
int *arr = (int*)malloc(sizeof(n)); //动态分配数组 它会向内存申请一块连续可用的空间,空间大小是 size 个字节,并返回指向这块空间的指针
printf("输入数组元素值: ");
for(int i = 0; i < n; i++){
scanf("%d", arr + i); //地址+1
}
for(int i = 0; i < n; i++){
printf("%d ", arr[i]);
}
printf("\n");
delete(arr, n);
for(int i = 0; i < n - 1; i++){
printf("%d ", arr[i]);
// 等同于 printf("%d ",arr + i);
}
return 0;
}
知识点补充
malloc 是我们见得最多的动态内存函数。
它会向内存申请一块连续可用的空间,空间大小是 size 个字节,并返回指向这块空间的指针。
它返回的是个指针,所以在使用它时要用指针接收:
char* ch = malloc(sizeof(char) * size1);
int* arr = malloc(sizeof(int) * size2);
struct S* s = malloc(sizeof(stuctt S) * size3);
但这样并不严谨,因为 malloc 返回类型是空指针,所以在接受它的返回值时最好再对它进行强制类型转换:
char* ch = (char*)malloc(sizeof(char) * size1);
int* arr = (int*)malloc(sizeof(int) * size2);
struct S* s = (struct S*)malloc(sizeof(stuctt S) * size3);
但是,当动态内存开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查:
char* ch = (char*)malloc(sizeof(char) * size);
if(ch == NULL)
{
perror("fun_name");
return;
}
2.
#include <stdio.h>
#include <stdlib.h>
void reverse(int *arr, int len){
int tmp;
for (int i = 0; i < len / 2; i++){
tmp = *(arr + i);
*(arr + i) = *(arr + len -i - 1);
*(arr + len - i - 1) = tmp;
}
}
int main(){
int n; //数组元素个数
printf("输入数组元素个数n= ");
scanf("%d", &n);
int *arr = (int*)malloc(sizeof(n)); //动态分配数组
printf("输入数组元素值: ");
for(int i = 0; i < n; i++){
scanf("%d", arr + i);
}
for (int i = 0; i < n;i++){
printf("%d ", *(arr + i));
}
printf("\n");
reverse(arr, n);
for (int i = 0; i < n;i++){
printf("%d ", *(arr + i));
}
return 0;
}
3.
#include <stdio.h>
#include <stdlib.h>
int delX(int *arr, int len, int x){
int k = 0, i = 0; //k记录删除元素的总数
while (i < len){
if(*(arr + i) == x){
k++;
}
else{
*(arr + i - k) = *(arr + i);
}
i++;
}
for(int i = len - k; i < len; i++){
*(arr + i) == NULL;
}
return k;
}
int main(){
int arr[] = {1,2,3,2,2,4};
int len = sizeof(arr) / sizeof(int), k; // int型数组,数组的大小除以int型数据的大小,得到数组的长度。
k = delX(arr, len, 2);
for(int i = 0; i < len - k; i++){
printf("%d ", *(arr + i));
}
return 0;
}
补充:
sizeof是计算数据(包括数组、变量、类型、结构体等)所占内存空间,用字节数表示。
在32位的系统中,sizeof(int)的值为4。如果x是int型的数组,则sizeof(x)/sizeof(int)代表x的位数。
4.
#include <stdlib.h>
void deletePoint(int *arr, int s, int t, int len){
int k = 0, i = 0;
for (i = 0; i < len && *(arr + k) < s; i++); // 找到第一个大于s的元素
if (i >= len) return;
for (k = i; k <= len && *(arr + k) <= t; k++); // 找到第一个大于t的元素
for (; k < len; i++, k++){
*(arr + i) = *(arr + k);
}
printf("当前数组为:");
for (int j = 0; j < i; j++){
printf("%d ", *(arr + j));
}
}
int main(){
int arr[] = {1, 2, 4, 6, 10, 15};
int s, t;
int len = sizeof(arr) / sizeof(int); // 计算数组元素个数
do{ // 输入区间范围
printf("s = ");
scanf("%d", &s);
printf("t = ");
scanf("%d", &t);
}while (s > t);
deletePoint(arr, s, t, len);
return 0;
}
5.
同第三题
6.
#include <stdio.h>
#include <stdlib.h>
int deleteRepitition(int *arr, int len){ // C语言无法直接修改数组长度,这里返回去重后的数组长度
int k = 0;
for (int i = 0; i < len; i++){ // 判断前后元素是否相同
if(*(arr + i) - *(arr + i + 1)){
*(arr + k++) = *(arr + i);
}
}
if(*(arr + len - 1) == *(arr + len)){ // 最后一个元素处理(如果最后一个元素和后一个存储空间的元素相同)
*(arr + k++) = *(arr + len - 1);
}
return k;
}
int main(){
int arr[] = {1,1,2,2,2,3,3,4,5,5};
int len = sizeof(arr) / sizeof(int); // 数组元素个数
len = deleteRepitition(arr,len);
for(int i = 0; i < len; i++){
printf("%d ", *(arr + i));
}
return 0;
}
7.
#include <stdio.h>
#include <stdlib.h>
int *mergeList(int *l1, int *l2, int len1, int len2){
int *newArr = (int *)malloc(len1 + len2);
int k = 0, i = 0, j = 0;
for (; i < len1 && j < len2;){
*(l1 + i) < *(l2 + j) ? *(newArr + k++) = *(l1 + i++) : *(newArr + k++) = *(l2 + j++);
//条件运算符的优先级比赋值运算符的优先级高,在一些编译器中需要加括号,建议使用下面if语句
// if (*(l1 + i) < *(l2 + j)){
// *(newArr + k++) = *(l1 + i++);
// }
// else{
// *(newArr + k++) = *(l2 + j++);
// }
}
while(i < len1){
*(newArr + k++) = *(l1 + i++);
}
while(j < len2){
*(newArr + k++) = *(l2 + j++);
}
return newArr;
}
int main(){
int l1[] = {1,3,5,7,8};
int l2[] = {2,4,4,6};
int len1 = sizeof(l1) / sizeof(int); // 数组元素个数
int len2 = sizeof(l2) / sizeof(int);
int *res;
res = mergeList(l1, l2, len1, len2);
for (int i = 0; i < len1 + len2; i++){
printf("%d ", *(res + i));
}
return 0;
}
补充:
条件表达式的优先级顺序:
(e < a[mi]) ? (hi = mi) : (lo = mi +1);
程序完美运行,这也就提示我们要经常加括号。
条件运算符的优先级比赋值运算符的优先级高,所以通常条件运算符的用法如下:
x = y < 0 ? -y : y; //求一个数的绝对值;
附:
①、上面的例子的使用的编译器是codeblocks,报错。但是同样是不加括号,在c-free下是可以运行的,编译器之间还是有少许的区别的。
②、在线编译器有时候还真的挺好用,可以测试程序的正确性啊。虽然缺点是速度慢点,还不能保存。
③、在线编译器:菜鸟教程在线编译器、ideone、dooccn,特别是dooccn,界面炫酷友好,操作还比较方便。
8.
#include <stdio.h>
#include <stdlib.h>
void reverse(int *arr, int from, int end){
if (from > end){
return;
}
int tmp;
for (int i = from; i <= (from + end) / 2; i++){
tmp = *(arr + i);
*(arr + i) = *(arr + end - i + from);
*(arr + end - i + from) = tmp;
}
}
int main(){
int arr[] = {1,2,3,4,5,11,22,33,44,55, 66};
reverse(arr, 0, 10);
reverse(arr, 0, 5);
reverse(arr, 6, 10);
for (int i = 0; i< 11; i++){
printf("%d ", *(arr + i));
}
return 0;
}
补充:
这里用到了逆置思想,先整体逆置,再分别逆置,这样复杂度最小
9.
#include <stdio.h>
#include <stdlib.h>
int findX(int *arr, int len, int x){
int low = 0, high = len - 1, mid;
while (low <= high && (mid = (low + high) / 2)){ // 折半查找
if ( x == *(arr + mid)){
break;
}
if (x < *(arr + mid)){
high = mid -1;
}
else{
low = mid + 1;
}
}
if (low > high){ // 未找到,插入该元素
int i;
for (i = len - 1; i > high; i--){
*(arr + i + 1) = *(arr + i);
}
*(arr + i + 1) = x;
return len + 1;
}
else{ // 找到了,和下一元素对调
int tmp = *(arr + mid);
*(arr + mid) = *(arr + mid + 1);
*(arr + mid + 1) = tmp;
return len;
}
}
int main(){
int arr[10] = {1,3,4,5,7,22,37,41}; // 为便利,创建十个元素的数组,放入八个元素
int x, len;
scanf("%d", &x); // 输入需要查找的数
len = findX(arr, 8, x);
for (int i = 0; i< len; i++){
printf("%d ", *(arr + i));
}
return 0;
}
补充:
题目要求用时最少,折半查找用时最少
10.
和第8题相似
#include <stdio.h>
#include <stdlib.h>
void reverse(int *arr, int from, int end){
if (from > end){
return;
}
int tmp;
for (int i = from; i <= (from + end) / 2; i++){
tmp = *(arr + i);
*(arr + i) = *(arr + end - i + from);
*(arr + end - i + from) = tmp;
}
}
int main(){
int arr[] = {1,2,3,4,5,6,7,8,9,10};
reverse(arr, 0, 9);
reverse(arr, 4, 9);
reverse(arr, 0, 9);
for (int i = 0; i< 10; i++){
printf("%d ", *(arr + i));
}
return 0;
}
11.
#include <stdio.h>
#include <stdlib.h>
int findMidNum(int *l1, int *l2, int len){ // 这里题目要求两个数组一样长,那么可以得出中位数必是排序后第一个数组最后一个元素,即第len-1个元素
int count = 0, midlle;
for (int i = 0, j = 0; *(l1 + i) && *(l2 + j);){
if (count++ == len){
if (*(l1 + i) < *(l2 + j)){
midlle = *(l1 + i);
}
else{
midlle = *(l2 + j);
}
break;
}
else{
if (*(l1 + i) < *(l2 + j)){
i++;
}
else{
j++;
}
}
}
return midlle;
}
int main(){
int l1[] = {1,3,5,7};
int l2[] = {2,4,6,8};
int len = sizeof(l1) / sizeof(int); // 数组长度
printf("中位数的值为:%d", findMidNum(l1, l2, len -1));
return 0;
}
12.
#include <stdio.h>
#include <stdlib.h>
int findMidNum(int *arr, int len){ // "两两抵消",最后留下最多个数元素,再判断是否是主元素
int count = 1, c = *arr, mainCount;
for (int i = 1; i < len; i++){
if (c == *(arr + i)){
count++;
}
else{
if(count > 0){
count--;
}
else{
c = *(arr + i);
count = 1;
}
}
}
if (count > 0){
for (int i = 0; i < len; i++){
if (*(arr + i) == c){
mainCount++;
}
}
}
if (mainCount > len / 2){
return c;
}
else{
return -1;
}
}
int main(){
int arr[] = {0,5,5,3,5,7,5,5};
int mainNum;
mainNum = findMidNum(arr, 8);
printf("%d",mainNum);
return 0;
}
13.
#include <stdio.h>
#include <stdlib.h>
int findMin(int *arr, int n){
int *arrB = (int *)malloc(sizeof(int) * n);
// arr[i] > 0 ? arrB[arr[i] - 1] = 1 : arrB[i] = 0;
for (int i = 0;i < n; i++){ // arrB元素置0
arrB[i] = 0;
}
for (int i = 0; i < n; i++){
if (arr[i] > 0){
arrB[arr[i] - 1] = 1;
}
}
for (int k = 0;k < n; k++){ //数组中第一个为0的元素下标+1即为最小正整数
if (arrB[k] == 0){
return k + 1;
}
}
return n + 1;
}
int main(){
int arr[] = {1,2,3,4};
int min = findMin(arr, 4);
printf("%d",min);
return 0;
}
14.
#include <stdio.h>
#include <stdlib.h>
int dis(int a, int b, int c){ //返回距离
return abs(a - b) + abs(b - c) + abs(a - c);
}
int min(int a, int b, int c){ // 返回当前最小值,移动指针
if(a < b && a < c)
return a;
else if(b < c && b < a)
return b;
else
return c;
}
int findMinofTrip(int *s1,int *s2,int *s3,int len1,int len2,int len3){
int i = 0, j = 0, k = 0; // 数组下标,遍历数组
int Max = 10000; // 假设一个最大值
int nowD = 0;
while(i < len1 && j < len2 && k < len3){
nowD = dis(s1[i], s2[j], s3[k]);
if (nowD < Max)
Max = nowD;
if (s1[i] == min(s1[i], s2[j], s3[k]))
i++;
else if (s2[j] == min(s1[i], s2[j], s3[k]))
j++;
else
k++;
}
return Max;
}
int main(){
int S1[] = {-1,0,9};
int S2[] = {-25,-10,10,11};
int S3[] = {2,9,17,30,41};
int minD = findMinofTrip(S1,S2,S3,3,4,5);
printf("%d",minD);
return 0;
}