【C1】数据结构实现基础
啦啦啦,澜子又要开始瞎鼓捣啦。最近觉得数据结构好有意思,所以想要整理一个系列,方便自己后续复习,也可以便利大噶。虽然很菜,一直不停滴在写BUG(划重点),就是那种 只有你想不到的BUG,没有我写不出的BUG(心累脸) 。可能写得有点乱七八糟,但是还是想要整理整理,还是那句话,不对的地方一定告诉我,一起改进,然后也很希望能和大噶共同分享啦。
后续系列博客都是基于陈越老师主编的《数据结构》一书。本篇博客的主要内容有:
- 数据结构的基本介绍
- 基本C/C++语法
- 简单的应用实例:求无序数组中位数的两种实现
引子
抽象出针对基本统计要求的数据类型
- 类型名称
- 数据对象集
- 操作集
数据存储基础
数组
- 一维数组定义
- 类型名 数组名[数组长度]
- 一维数组引用
- 数组名[下标]
- 数组初始化
- 类型名 数组名[数组长度] = {初值表}
- 二维数组定义
- 类型名 数组名[行长度][列长度]
- 二维数组应用
- 数组名[行下标][列下标]
指针
- 指针定义
- 类型名 *指针变量名
- 指针用于存放变量的地址,定义指针变量时,需注意
- 给出指针变量名
- 说明指针变量所指向的内存空间存放的数据类型
- 指针变量应该先赋值,后使用
- 指针的基本使用
- 指针的基本运算
- 指针与数组
- 用指针实现内存动态分配
- P.S: 动态存储分配函数—
void *malloc(unsigned size):
在内存的动态存储区中分配一连续空间,其长度为size,若申请成功,则返回一个指向所分配内存空间的内存其实地址;若申请内存空间不成功,则返回NULL(值为0)
。该函数的返回值为(void *)类型
,在具体使用中,需要将 **malloc的返回值转换到特定指针类型,并赋给一个指针变量
结构
- 结构定义的一般形式
struct 结构名
{
类型名 结构成员名1;
类型名 结构成员名2;
...
类型名 结构成员名n;
};
- 定义结构体变量的方式:先定义一个结构类型,再定义一个具有这种结构类型的嵌套
- struct 结构名 结构变量名表;
- 结构变量的使用
- 结构变量名.结构成员名
- 结构指针
- `(* 结构指针变量名).结构成员名
- 结构指针变量名->结构成员名
链表[详见陈越老师《数据结构》第二章C2]
链表是一种常见而重要的基础数据结构,其不按照线性顺序存储数据,而是由若干个同一结构类型的结点一次串接而成。主要掌握链表的建立,插入,删除,遍历。
- 单向链表
- 双向链表
- 循环链表
类型定义—typedef
利用typedef来建立基本数据类型的别名可使程序具有更好的可读性和移植性
- 定义形式
- typedef 原有类型名 新类型名
流程控制基础
分支控制
- if else
- switch
循环控制
- for语句
- while语句
- do while语句
函数与递归 [详见应用实例]
- TODO:汉诺塔
- 要求:函数先定义后调用
- 若主调函数放在自定义函数前,需在调用函数前,进行函数原型声明
- 函数声明一般格式
函数类型 函数名(参数表);
- 函数定义的基本形式
函数类型 函数名(形参表)
{
函数实现过程;
}
- 函数调用的一般形式
函数名(实参表);
- 递归函数【详见
find_kth_value_list.cpp
】- 关键点1:递归出口
- 关键点2:递归式子
SOME NOTES
- 计算机执行C程序时,先找
main主函数
,若遇到函数调用
,主函数被暂停执行,转而执行相应的函数;该函数执行完之后,返回主函数
,然后再从原先暂停的位置继续执行 - 函数定义中参数成为形参,函数调用时的参数称为实参。形参和实参必须一一对应,要求
两者数量相同,类型一致。
遇到函数调用,将实参的值一次传给形参,这就是参数传递 C语言规定,
参数传递过程中,将实参的值复制给形参。这种参数传递是单向的,
只允许实参把值复制给形参,而形参的值即使在函数中改变了,也不会反过来影响实参
应用实例
- 求解中位数问题:基于排序—
mid_value_sort.cpp
- 求解无序数组中的第k大的数字:基于问题分解 (递归)—
find_kth_value_list.cpp
求解中位数问题:基于排序—mid_value_sort.cpp
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int maxsize=9999;
// int raw_seq[maxsize];
int find_median_sort(int raw_seq[],int seq_num)
{
// int sorted_seq[seq_num];
sort(raw_seq,raw_seq+seq_num);
return raw_seq[seq_num/2];
}
/*
7
2 7 1 10 9 8 6
*/
int main()
{
int seq_num;
int raw_seq[seq_num];
int median;
cin >> seq_num;
for(int i=0;i<seq_num;i++)
cin >>raw_seq[i];
median = find_median_sort(raw_seq,seq_num);
cout << "median is " << median;
}
求解无序数组中的第k大的数字(基于问题分解—递归)
- 当
k=2/n
,n为数组内元素个数,即为求解中位数问题 - 我理解的递归的实质:函数调用的压栈和出栈
#include <iostream>
using namespace std;
const int maxsize = 9999;
int find_kth_value(int seq[],int k,int left,int seq_num)
{
cout << "left is "<<left<<" ";
int pivot = seq[left];
cout << "pivot is "<<pivot<<" "<<endl;
int less_seq[maxsize];
int large_seq[maxsize];
int s1_cnt,s2_cnt = 0;
for(int i=0;i<seq_num;i++)
{
if(seq[i]>=pivot)
{
large_seq[s1_cnt] = seq[i];
s1_cnt++;
}
else
{
less_seq[s2_cnt] = seq[i];
s2_cnt++;
}
}
if(s1_cnt>k) return find_kth_value(large_seq,k,1,s1_cnt);
else if(s1_cnt<k) return find_kth_value(less_seq,k-s1_cnt,0,s2_cnt);
else return pivot;
}
/*
9
3
6 5 9 8 2 1 7 3 4
*/
int main()
{
int seq_num;
cin >> seq_num;
int k;
cin >> k;
int seq[seq_num];
int kth_value;
for(int i=0;i<seq_num;i++)
cin >> seq[i];
kth_value = find_kth_value(seq,k,0,9);
cout << "kth value is " << kth_value;
}