【C1】数据结构实现基础

本文介绍了数据结构的基础知识,包括数组、指针、结构体和链表的概念与应用。重点讲解了一维和二维数组的定义与引用,以及指针的使用。此外,还探讨了递归的基础,包括递归函数的关键点和应用实例,如求解无序数组的中位数和第k大数字问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值