数据结构入门1
重学数据结构的一段日子, 看看408吧, 所以用的c语言.
当前是看郝斌 数据结构入门视频课, 希望进度快一些. 然后就能看其他的书和进阶的公开课了.
这两天才写了一个函数: 线性存储结构的连续存储 数组嘛.
/*
写程序步骤
1. 伪代码/简易代码 写出 所有功能的实现流程
2. 将所有的功能具体实现
3. 在程序中输入数据测试功能
*/
#include <stdio.h>
#include <malloc.h> // malloc 函数
#include <stdbool.h> // 布尔函数
// 名为struct Arr的数据类型
struct Arr {
int* pBase; // 数组中第一个元素地址, 数组指针
int len; // 数组长度
int current; // 当前数组元素个数
};
/*
1.初始化条件
2.使用函数提供那些参数以及参数的条件
3.该函数实现的功能
*/
void init_arr(struct Arr* pArr, int length); // 初始化数组
bool append_arr(struct Arr* pArr, int val); // 尾部追加元素
bool insert_arr(struct Arr* pArr, int pos, int val); // 指定位置添加元素
bool delete_arr(struct Arr* pArr, int pos, int* pVal); // 删除元素, 并返回删除值
bool is_empty(struct Arr* pArr); // 判断空
bool is_full(struct Arr* pArr); // 判断满
void sort_arr(struct Arr* pArr); // 数组排序
void show_arr(); // 打印数组元素
void invers_arr(struct Arr* pArr); // 倒置数组
int main(void) {
struct Arr arr;
int val;
init_arr(&arr, 6); // 将arr的地址赋给 init_arr 函数
//show_arr(&arr);
/*
顺序添加元素
append_arr(&arr, 1);
append_arr(&arr, 2);
append_arr(&arr, 3);
append_arr(&arr, 4);
append_arr(&arr, 5);
insert_arr(&arr, 1, 0);
//show_arr(&arr);
*/
//逆序元素
//invers_arr(&arr);
/*
//pVal用于存放pArr元素地址的 &val=*pArr
if (delete_arr(&arr, 1, &val)) {
printf("删除成功! 删除的元素为:%d\n", val);
} else {
printf("删除失败!\n");
}
*/
//show_arr(&arr);
/*
if (append_arr(&arr, 7)) {
printf("追加成功!\n");
} else {
printf("追加失败哦.\n");
}
*/
append_arr(&arr, 87);
append_arr(&arr, 45);
append_arr(&arr, 3);
append_arr(&arr, 122);
append_arr(&arr, 537);
append_arr(&arr, 486);
show_arr(&arr);
sort_arr(&arr);
show_arr(&arr);
return 0;
}
// 通过Arr* 接收 &arr 赋给的地址
// 初始化数组函数
init_arr(struct Arr* pArr, int length) {
// 指针 pArr 指向结构体变量中pBase成员
// 用malloc动态分配的内存空间
pArr->pBase = (int*)malloc(sizeof(int) * length);
// pBase 为内存空间中第一个变量地址, 用于标记整个数组, int占用4个字节, int*length就是占用的具体字节数
// 如果动态内存分配失败, malloc函数会将 NULL 值赋给pBase 需要检测pBase值是否为NULL
if (NULL == pArr->pBase) {
printf("动态内存分配失败!\n");
exit(-1); // 终止整个程序
} else {
pArr->len = length;
pArr->current = 0;
}
return;
}
_Bool is_empty(struct Arr* pArr) {
if (0 == pArr->current) {
return true;
} else {
return false;
}
}
//判断当前数组是否存满
_Bool is_full(struct Arr* pArr) {
//判断结构体pArr当前元素个数是否等同于数组长度
if(pArr->current == pArr->len) {
return true;
} else {
return false;
}
}
void show_arr (struct Arr* pArr) {
// pArr是多重指针, 此时pArr的参数就是pArr地址, 因为是show_arr函数传入的参数, 所以不需要添加任何符号
if( is_empty(pArr)) {
printf("数组为空!\n");
} else {
for(int i=0; i<pArr->current; ++i) {
//pArr为结构体, 不是数组. 要打印数组就需要用地址将数组中的数组
printf("%d ", pArr->pBase[i]);
}
printf("\n");
}
}
//追加数组中元素
_Bool append_arr(struct Arr* pArr, int val) {
//先判断数组是否存满
if(is_full(pArr)) {
// 存满返回false
return false;
} else {
// 没存满, 将val的值追加到数组pArr中
//数组从0开始计数, current就表示当前的要存入的位置
pArr->pBase[pArr->current] = val;
//追加数字后, 要把现存数据的变量+1表示多存了一个数据
pArr->current++;
return true;
}
}
_Bool insert_arr(struct Arr* pArr, int pos, int pVal) {
int i;
//判断数组是否满
if (is_full(pArr))
return false;
// 保证输入的参数符合预期, 加入条件判断
// 插入数据的位置pos必须大于1, pos的数值不能大于当前数组元素个数+1
if (pos<1 || pos>pArr->current+1)
return false;
// i的值为当前个数的减一, 因为下标从0开始
// 因为下标从0开始数, 需要移动的值是pos-1, 这样和下标值契合的
// 比如说一个6位数组, 那下标为012345, 六个位置, 如果要在pos=3处插入一个元素, 换算到数组下标就是3-1为2
// i数组中当前最后一个元素的下标, i的最大合法值, 这个循环是从后向前移动的
for(i=pArr->current-1; i>=pos-1; --i) {
pArr->pBase[i+1] = pArr->pBase[i];
}
// 将val的值赋给要插入的位置, 因为下标从0开始所以要-1
pArr->pBase[pos-1] = pVal;
// 添加了一个新元素, 当前current下标+1
(pArr->current)++;
}
_Bool delete_arr(struct Arr* pArr, int pos, int* pVal) {
int i;
if(is_empty(pArr))
return false;
//判断数组非空后判断数组删除元素位置不能小于1同时大于当前值
if (pos<1 || pos>pArr->current)
return false;
// 将要删除的值赋给pVal用于打印
*pVal = pArr->pBase[pos-1];
// i等于要删除的位置, i小于当前元素个数, i递增用于逐位将下标的值向前移动
for(i=pos; i<pArr->current; i++) {
// 将下标向前移动一位
pArr->pBase[i-1] = pArr->pBase[i];
}
// 删除后将当前的数组上限-1
pArr->current--;
return true;
}
invers_arr(struct Arr* pArr) {
int i = 0;
int j = pArr->current-1;
int temp;
struct Arr arr;
while (i<j) {
/*
两个变量值交换通常借助第三个值temp进行交换
temp = i
i = j
j = temp
*/
temp = pArr->pBase[i];
pArr->pBase[i] = pArr->pBase[j];
pArr->pBase[j] = temp;
++i; // 将数组下标从0开始向后移动一位
--j; // 将数组下标从最后一位向前移动一位
//打印当前pArr数组元素
//show_arr(pArr);
}
return;
}
// N2的冒泡排序
// 感觉不像排序, 排序应该是指定一个最小值和之后的所有元素比较, 这个还是类似冒泡
void sort_arr(struct Arr* pArr) {
int i, j, temp;
for(i=0; i<pArr->current-1;i++) {
for(j=i+1; j<pArr->current; ++j) {
if(pArr->pBase[i] > pArr->pBase[j]) {
temp = pArr->pBase[i];
pArr->pBase[i] = pArr->pBase[j];
pArr->pBase[j] = temp;
}
}
}
}