郝斌老师数据结构视频学习记录。
涉及到数组的初始化、插入、删除、查找、翻转、排序等。
#include <stdio.h> #include <malloc.h> #include <stdlib.h> #include <stdbool.h>
struct Arr { int* pBase; int len; int cnt; };
void Init_arr(struct Arr* pArr, int len); void Get_arr(struct Arr* pArr, int val); bool Is_empty(struct Arr* pArr); bool Is_full(struct Arr* pArr); 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);
void Show_arr(struct Arr* pArr); void Inversion_arr(struct Arr* pArr); void Sort_arr(struct Arr* pArr);
int main(void) { struct Arr arr; int val; Init_arr(&arr, 6); Show_arr(&arr); Append_arr(&arr, 1); Append_arr(&arr, 10); Append_arr(&arr, -3); Append_arr(&arr, 6); Append_arr(&arr, 88); Append_arr(&arr, 11); Get_arr(&arr, 4); Insert_arr(&arr, 6, 99); if( Delete_arr(&arr, 4, &val) ){ printf("删除成功\n"); printf("删除的元素是:%d\n", val); } else{ printf("删除失败!\n"); }
Show_arr(&arr); Inversion_arr(&arr); printf("倒置之后的数组内容是:\n"); Show_arr(&arr); Sort_arr(&arr); printf("排序后的数组内容是:\n"); Show_arr(&arr); return 0; }
void Init_arr(struct Arr* pArr, int len) { pArr->pBase = (int*)malloc(sizeof(int)* len); if(NULL == pArr->pBase) { printf("动态分配内存失败!\n"); exit(-1); } else { pArr->len = len; pArr->cnt = 0; } return; }
void Get_arr(struct Arr* pArr, int val){ if( Is_empty(pArr) ) printf("获取下标失败!\n"); else { for(int i=0; i<pArr->cnt; i++){ if(pArr->pBase[i] == val) { printf("%d的数组下标为:", val); printf("%d\n", i); } } } }
bool Is_empty(struct Arr* pArr) { if(0 == pArr->cnt) return true; else return false; }
bool Is_full(struct Arr* pArr) { if(pArr->cnt == pArr->len) return true; else return false; }
void Show_arr(struct Arr* pArr){ if(Is_empty(pArr)) { printf("数组为空!\n"); } else { for(int i=0; i<pArr->cnt; i++) { printf("%d ", pArr->pBase[i]); } printf("\n"); } }
bool Append_arr(struct Arr* pArr, int val){ if( Is_full(pArr) ) return false; else { pArr->pBase[pArr->cnt] = val; (pArr->cnt)++; return true; } }
bool Insert_arr(struct Arr* pArr, int pos, int val){ if(Is_full(pArr)) return false; if(pos<1 || pos>pArr->cnt+1) return false; for(int i=pArr->cnt-1; i>=pos-1; i--){ pArr->pBase[i+1] = pArr->pBase[i]; } pArr->pBase[pos-1] = val; (pArr->cnt)++; return true; }
bool Delete_arr(struct Arr * pArr, int pos, int * pVal) { if(Is_empty(pArr)) return false; if(pos<1 || pos>pArr->cnt) return false; *pVal = pArr->pBase[pos-1]; for(int i=pos; i<pArr->cnt; i++){ pArr->pBase[i-1] = pArr->pBase[i]; } pArr->cnt--; return true; }
void Inversion_arr(struct Arr* pArr){ int t; for(int i=0; i<pArr->cnt/2; i++){ t = pArr->pBase[i]; pArr->pBase[i] = pArr->pBase[pArr->cnt-1-i]; pArr->pBase[pArr->cnt-1-i] = t; } }
void Sort_arr(struct Arr* pArr){ int t; for(int i=0; i<pArr->cnt-1; i++){ for(int j=i+1; j<pArr->cnt; j++){ if(pArr->pBase[i] > pArr->pBase[j]){ t = pArr->pBase[i]; pArr->pBase[i] = pArr->pBase[j]; pArr->pBase[j] = t; } } } }
|
其中Inversion_arr翻转数组可以使用折半方法:
void Inversion_arr(struct Arr* pArr){ int t; for(int i=0; i<pArr->cnt/2; i++){ t = pArr->pBase[i]; pArr->pBase[i] = pArr->pBase[pArr->cnt-1-i]; pArr->pBase[pArr->cnt-1-i] = t; } }
|
相比于下面这种方法:
void Inversion_arr(struct Arr* pArr){ int i = 0, j = pArr->cnt-1, t; while(i<j){ t = pArr->pBase[i]; pArr->pBase[i] = pArr->pBase[j]; pArr->pBase[j] = t; i++; j--; } }
|
这种方法并不是最优解,因为它需要使用额外的空间来存储输入的数组,即使是在原地翻转数组的情况下,交换的操作次数也更多。
而第一种方法更简洁的方法在不使用额外空间的情况下原地翻转数组,而且只需要一次遍历,每次将首尾元素进行交换,从而实现原地翻转数组。
下面再看查找数组,相信你已经猜到了,当然是二分啦!
void Get_arr(struct Arr* pArr, int val){ if( Is_empty(pArr) ){ printf("获取下标失败!\n"); } else{ for(int i=0;i<pArr->cnt;i++){ if(pArr->pBase[i] == val){ printf("%d的数组下标为:", val); printf("%d\n", i); } } } }
|
上面这种方法是最笨、但也是最容易理解的方法,但是效率太低了。
那么就对它使用二分吧:
int Get_arr(struct Arr* pArr, int val){ int left = 0; int right = pArr->cnt-1; while(left <= right){ int middle = (left + right)/2; if(val < pArr->pBase[middle]){ right = middle-1; } else if(val > pArr->pBase[middle]){ left = middle+1; } else return middle; } return -1; }
|
int Get_arr_2(struct Arr* pArr, int val){ int left = 0; int right = pArr->cnt; while(left < right){ int middle = (left + right)/2; if(val < pArr->pBase[middle]){ right = middle; } else if(val > pArr->pBase[middle]){ left = middle+1; } else return middle; } return -1; }
|