达内C语言数据结构(DAY17)

回顾:

1.数据结构

​ 先进后出

​ 操作栈顶

队列

​ 先进先出FIFO

​ 入队操作队尾

​ 出队操作队首

单链表

struct node {
	数据;
	struct node *next;
};

双链表

struct node {
	数据;
	struct node *next, *prev;
};

描述链表的结构体
struct list {
	struct node head/*head;
	struct node tail/*tail;
};

二叉树

​ 有序二叉树:左小于右

​ 先序 / 中序 / 后序

struct node {
	数据:
	struct node *left, *right;
};

​ 利用递归函数实现操作

2. gdb代码调试工具(单步跟踪调试程序)

使用步骤:

  1. 编译程序时,一定要加-g选项(调试选项)

    gcc -g -o helloworld helloworld.c   //一定要添加-g选项
    
  2. 调试程序需要启动gdb命令,立马出现gdb的命令提示符:(gdb)

    gdb命令格式:gdb 可执行程序文件名
    例如:
    	gdb helloworld
    
  3. 掌握几个gdb命令

    (gdb)l    // l = list;罗列源代码
    (gdb)b     // b = breakpoint=断点
    			// b 15就是在15行设置一个断点
    (gdb)r     //r = run;启动运行程序,CPU就从main函数开始依次向下运行,知道遇到断点
    (gdb)s     // s = step 下一步; 让CPU继续向下执行一条语句,如果碰到函数,会让CPU进入函				数继续跟踪
    			//如果输入n(next),也就是下一步,但是CPU不会进入函数内存跟踪,直接调用函数					完毕
    (gdb)p 变量名   //查看变量的值
    (gdb)p /x 变量名  //查看变量的值,按照16进制	格式输出
    (gdb)q        //quit  ,退出gdb命令
    

3. 常用算法

4个排序算法和2个查找算法:

3.1 冒泡排序算法

例如:

初始状态:	9	7	5	3	1
第一趟:	 7   5	 3   1   9   9>7交换位置,9>5交换,9>3交换,9>1交换
第二趟:	 5   3   1   7   9   7>5交换位置,7>3交换位置,7>1交换位置,7<9不交换
第三趟:	 3   1   5   7   9   5>3交换位置,5>1交换位置,5<7不交换,5<9不交换
第四趟:	 1   3   5   7   9   3>1交换,3<5不交换,3<7不交换,3<9不交换

目前来看:N个数需要N-1躺排序,每趟需要N-1次比较

第一步优化:N个数需要N-1趟排序,每趟需要N-1-i次比较 减1是因为下标是从0开始的

第二步优化:

初始状态: 0 7 5 3 1

第一趟: 0 5 3 1 7

第二趟: 0 3 1 5 7

第三趟: 0 1 3 5 7

如果发现某一趟的排序中,没有发火时呢个数据的囧啊换,那么就认为排序完成

参考代码:文件夹bubble_sort

https://gitee.com/cui-qinghe/c-study-notes.git 代码

3.2 插入排序算法

例如:

初始状态:10	30	20	15	5   //无序的
原始想法://有序的
		5	10	15	20	30
原始想法思路:从无序的数列中取出数据单独存放成一个有序的数列
			弊端:需要额外开辟内存空间来存放有序数据列
			解决办法:原地完成插入,不需要额外开辟大量内存空间
原地实现插入流程:
初始状态:10	30	20	15	5   //无序的
定义一个变量保存要被插入的数据,思路:
10	30	20	15	5  直接从第二个数据插

优点:节省了内存空间,只需一个变量保存被插入的数据即可原地完成排序

3.3 选择排序算法

例如:

初始状态:9	5	7	3	1   //无序
原始想法:1	3	5	7	9   //有序
思路:从一个数列中找最小数放到第一个位置,然后从剩余的无序数列中再找一个最小数
	 放在无序的第一个位置,依次排下去
弊端:需要额外开辟内存空间内存来存放有序数据列
解决方法:
初始状态:9	5	7	3	1
原地解决:1	5	7	3	9
		1	3	7	5	9
		1	3	5	7	9
		1	3	5	7	9      
参考代码:select_sort文件夹

https://gitee.com/cui-qinghe/c-study-notes.git 代码

3.4 快速排序

例如:

0	10	80	30	50	40	70	20	9	100

思路:不管在站在哪个数上去看,它左边的数小于它,它右边的树大于它(跟有序二叉树一样)

原始实现:站在50来看,进行一次分组得到:把比50小的放左边,大的放右边:
0	10	30	40	50	60	70	90	80	100   // 更接近有序
然后再对50左边的数进行再次分组,把比30小的放左边,大的放右边,
再然后队50右边的数进行再次分组,把比90小的放左边,小的放右边
0	20	10	30	40	50	60	80	70	90	100  //又接近有序
以此类推:对30左边右边进行各种分组,对90左边和右边各种分组
直到分到没有数或者只有一个数
弊端:需要开辟内存空间来存放不断趋近有序数列

	0	10	80	30	60	50	40	70	20	90	100
50为基准:0	10	30	20	40	50	60	70	90	80	100
30,90为基准:0	20	10	30	40	50	60	80	70	90	100
20,80为基准:0	10	20	30	40	50	60	70	80	90	100
10,70为基准:0	10	20	30	40	50	60	70	80	90	100

问:怎样能够实现原地分组呢?
答:定义三个游标来实现原地分组(p = pivot=基准)

初始:
    0	10	80	30	60	50	40	70	20	90	100
    i
    					p
    										j
50为基准进行依次(将来定义变量来缓存):
0	10	20	30	40	50	80	70	60	90	100
					i
    				p
    				j
参考代码:quick_sort

https://gitee.com/cui-qinghe/c-study-notes.git 代码

3.5 查找算法:线性查找,二分查找(折半查找)

1.线性查找:

在数列中挨个匹配要找的数据

对数据的有序性没有要求

参靠代码:find
2.二分查找(折半查找)

切记:二分查找的前提是的数据必须有序,否则用不了

原理:目标找60

10	20	30	40	50	60	70
对数列对半,然后拿60跟40比较,如果相等,说明找到了
如果不相等,发现60大于40,说明60一定在40的右边
然后对40右边50	60	70再对半分,然后拿60跟中间的60进行比较,发现相等,说明找到了
如果不相等,并且小于,在左边继续对半分
如果不相等,并且大于,在右边继续对半分
参考代码:find

https://gitee.com/cui-qinghe/c-study-notes.git 代码

上一篇:2021-06-12# 学习以及成为想要成为的人day17


下一篇:2021-04-23 第一阶段day17