技能篇-数据结构和算法篇-基础算法与结构( 一 )

TZ:我们恐惧的往往不是黑暗,而是光明

一 : 科普一分钟

什么是数据结构和算法,二者有和联系呢.
其实一种是数据存储的方式,一种是一种实现功能的手段.
我最近经常做饭,打个比方,就好比做菜一样,我们所用的食材就是数据结构,我们做同样的菜,食材有新鲜的有不新鲜的,肉质有老的有嫩的,同样算法好比厨师的厨艺,有高手和菜鸟,两者的配合会产生各种奇妙的结果,所以算法和数据结构 是程序的重要组成部分.

二 : 数据结构简述和举例

1. 概述:何为数据结构?

数据结构其实就是计算机存储,组织数据的方式.
相互之间存在一种或者多种特定关系的数据元素的集合

2. 常见的数据结构有哪些?

大家都学过数据结构这门课程,接下来我们来复习一下,我们都学过哪些数据结构.
(1) 线性表
包括我们常用的数组,链表,栈,和队列.
(2)树
(3)图

3.常见的逻辑结构

什么是逻辑结构?个人理解就是有点"纸上谈兵"的意思,类似于草图或者说是思路结构
(1)集合结构 : 把杂乱的数据放进一个大锅里.

集合结构.jpg

(2)线性结构 : 内存是连续的,类似于"铁索连环"

线性结构 .jpg

(3)树形结构 : 这个结构的特点就是....暂时理解像一颗树就好了

树形结构 .jpg

(4)图形结构 : 这个结构特点内存可以是连续的 也可以是不连续的

图形结构

4.存储结构
说完了逻辑结构,我们说说存储结构,
(1) 顺序存储结构

顺序存储.jpg

(2)链式存储结构

链式存储结构.jpg
  1. 队列

假如此时我们做一个解密算法
把一个数据串 第一个数扔掉,第二个数放到尾部,第三个数扔掉,第四个数放到尾部.....等等, 删掉的数按照移除顺序就是我们要的结果 如何实现呢?

这其实就是队列 ,队列是先进先出的,就好像我们排队买票,先站排的人最先买到票,最先离开,好像两头开口的一个通道.

我们用head 来标注 队列头 用tail 来标注队列尾部
注意 这里说的队尾 是值 尾部后+ 1 的位置

#include <stdio.h>
int main()
 {
    int q[102] = {0,6,3,1,7,5,8,2,9,4},head,tail;
  //初始化队列
head = 1;
tail = 10;

while(head < tail){

//打印队首
printf("%d",q[head]);

//出队
head ++

//将新队首数添加到队尾

q[tail] = q[head];
tail++;
//再次队首移除出队
head++
}

return 0;
 }

6.栈
简单的说一下栈,我们吃的薯片或者弹夹,都类似栈,先进后出.
现在我们做个简单的小例子简单分析一下
做一个判断一个串 是否是回文
什么是回文, AABB ,ABBA ,ABCBA这种对称的叫回文

我们用一个指向栈顶的变量top

#include<stdio.h>
#include<string.h>
char a[101],s[101];
int i,len,mid,next,top;
gets(a)//读入一个串
len = strlen(a);
mid = len/2 - 1;

top = 0;
//mid前面数一次入栈
for(i = 0; i <= mid ;i++){
s[++top] = a[i];

}
//判断奇偶性
if(len%2 == 0)
  next = mid + 1;
else
 next = mid + 2;

//匹配
for(i = mext ; i<len-1;i++){
if(a[i] != s[stop])
breal;
top -- ;
}


if(top == 0){
printf("是回文");

}else{

printf("不是回文");
}
return 0;
  1. 链表
链表.jpg

每一个链表的节点有两个部分组成,左边的部分存放的是具体的数值,右边存放的是下一个节点的地址.我们可以用一个结构体来描述它

struct node{
int data;
struct node *next;
}

现在实现 插入某个数到序列里,简单来说就是拆链和补链的过程.

#include <sdio.h>
#include <stdlib.h>
struct node{
int data;
struct node *next;
};

int main(){
 struct node *head,*p,*q,*t;
int i,n,a;
scanf("%d",&n);
head = NULL;//初始化
for(i = 1;i <= n;i++)
{
scanf("%d",&a);
//动态申请空间
p = (stuct node*)malloc(sizeof(stuct node));
p->data = a;//存放到当前节点
p ->next = NULL;
if(head ==NULL){
  head = p;//创建第一个节点
}else{
    q->next= p;
}
q = p;


//输入插入的数
scanf("%d",&a);
t = head;
while(t != NULL){
if(t->next ==NULL || t-> next->data > a){
 p = (struct node*)malloc(sizeof( struct node));
  //核心
 p->data = a;
p->next= t->next;
t->next = p;
break; 

}

t= t->next;

}
}


//输出
t = head
while(t !=NULL){

printf("%d",t->data);
t= t->next;
}

return 0;
}

对于数据结构和其存储代码只是简单描述,日后慢慢讲解.

三 : 算法简述和常用基础算法-排序

在工作中和学习中我们经常听到算法算法的,在上学的时候我们通常会学习算法这门单独学科的课程,讲的主要是,通过计算机语言编程解决一些和应用题一样的一些问题.

好,算法可以理解为是一种手段,或者一种解决方式,一系列的计算步骤,用来将输入数据转化为输出结果

1.算法的意义

(1)用于解决特定的问题
(2)解决同一个问题的不同算法的效率常常相差很大,这种差距的影响往往比硬件和软件方便的差距还要大.

2. 常用算法

(1)排序
(2)加密

3. 算法的优劣

怎样科学的评判一个算法的优劣,算法那么重要,不同的算法会很大程度上影响运行效率
时间复杂度 : 估算程序指令的执行次数
空间复杂度 估算所需占用的存储空间

这两个的计算方式我们以后的博客仔细讲解

4. 算法的优化方向

(1)用尽量少的内存空间
(2)用尽量少的执行步骤
(3)空间换时间
(4)时间换空间

5. 排序算法

(1)桶排序

1965年有两个大神, E.J IssacR.C Singleton 提出来的基本思想.
下面简单总结一下这种算法的思想

#include <stdio.h>
int main()
{
int a[10] , i,j,t;
for (i = 0 ; i <= 10 ; i++)
{
//初始化一下数组
a[i] = 0;
};

//循环输入7个数 对应的数字放到对应的桶中
for (int i = 0 ; i <7; i++ )
{
scanf("%d",&t);
a[t]++;
};

//输出打印
for(i = 0; i<= 10;i++){
  for(j = 0;j <= a[i]; j++)
    printf("%d",i);//每个桶中的数出现几次就打印几次
};

return 0;
}

总结分析 : 这是一个简化版的桶排序实际上桶排序要复杂很多这里就是和大家分析一下思路,下面画一个图来捋顺一下

桶排序.jpg

每个桶的号码就是存放自己的专属数字,比如说1号桶专门存放的就是数字 1 5号桶专门存放 数组 5 初见几次 就往对应的桶里面 增加一次,也就是代码中的 a[t]++;

可以看的出来这种算法需要的空间很大,也就是说,我们要准备很多的 这点并不可取

接下来看看其时间复杂度O(M+N) (计算方式以后博客会说明)

(2)冒泡排序

1956 年就有人曾经研究过冒泡排序,之后很多人研究改进过,但结果都令人失望,正如 高德纳 所说 冒泡排序除了它迷人的名字和导致了某些有趣的理论问题这一事实之外,似乎没什么值得推荐的

#include <stdio.h>
int main(){

int a[100],i,j,t,n;
//输入n 个数存放到数组 a中
for(i = 0 ; i <= n ; i++){
   scanf("%d",&a[i]);
};

//冒泡排序交换核心
for(i = 0 ; j <= n-1;i++){
   for(j = 1 ; j < n - i;j++)
     {
         if( a[j] < a[j+1] ){
               t = a[j]; a[j] = a[j+1]; a[j+1] = t;
            }
     }
}

//输出结果 
for(i = 0 ;i <= n;i++){

printf("%d".a[i]);
}

return 0;
}

总结 : 冒泡排序就是两两交互比较大小,核心代码中的外层循环 是 走的 数 控制交换了几趟,每一趟都能决定出一个最大的数 或者 最小的数 ,为什么是 n-1 因为最后一趟不用跑也确定了,因为就剩下那一个数了,同理内层循环 n - i 因为每趟交换 确定了一个数 ,所以我们内层循环 的时候 就要 排除那个已经 确定的 数.

接下来看看 冒泡排序时间复杂度 ->O(N²)

(3)快速排序

1960年 东尼霍尔 提出了快速排序 ,之后又有人做了优化.

思路 : 简单排序就是确定一个数 基数基数左边的数小于基数(这里说的是递增),让基数右边的数大于基数,
然后再去基数左边做同样操作 ,基数右边做同样操作

接下来上图来分析一下

快速排序.jpg

图中 (1) 我们通常把首个数设置为基数 我们在序列左边放了一个检索 i 在 序列 右边放了一个检索 j 进行检索

当i 发现了 比 '6' 大的数则停下,当 j 发现了 比 6 小的数则停下,然后 把发现的数交换位置 如图(2)

交换完毕 i 和 j 继续移动 如图(3) 继续交换 最后 i 和 j 相遇 检索完毕

最后把 3 和 6 交换位置,以 6为基数的 检索结束 ,接下来 6 左边的数 和 6 右边的数进行 同理操作

#include <stdio.h>

int a[101],n;

//我们把排序封装成方法 参数 分别是 左边启点 和 右边启点
void quicksort (int left,int right){
int i,j,t,temp;

if(left > right)
return;
};


temp = a[left];//确定基数
i = left;
j = right;
while(i != j){
//右边先开始检索
while( a[j] >= temp && i < j)
     j--;
}

//从左往右检索
while( a[i] <= temp && i < j ){
  i++
}

//交换两个数的位置
if( i < j) //没有相遇
{
  t = a[i];
 a[i] = a[j];
a[j] = t;
}

}

//基数归位

a[left] = a[i];
a[i] = temp;

quicksort(left,i-1);//处理基数左边的
quicksort(i+1,right);//处理基数右边的

return;
}

  int main()
 {
 int i,j;
//读取数据
scanf("%d",&n);
for(i = 1;i < n;i++)
 scanf("%d",&a[1]);
}

//调用
quicksort(1,n);
//输出
for(i = 1; i <= n ;i++){
   printf("%d", a[i]);
}

return 0;

总结 : 为什么 j 要先移动,而 i 要后移动呢

因我我们把基数设置在了左边,我们假设一种特殊情况,就是数据序列已经是从小到大拍好了的,假如我们从左边开始检索,因为基数在左边,循环条件可订货满足,所以,i 肯定移动到下一个,所以就发生了错误,所以我们要右j边先移动.

四 : 总结

简单的聊过了数据结构和算法,一个好的程序,我们不仅要考虑它的运行速度,也要配上好的数据结构,也就是数据的存储方式,数据结构往往配合着算法的使用 更佳炫酷.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容

  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 5,164评论 0 52
  • 概述:排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    每天刷两次牙阅读 3,727评论 0 15
  • 查找和排序都是程序设计中经常用到的算法。查找相对而言较为简单,不外乎顺序查找、二分查找、哈希表查找和二叉排序树查找...
    eagleRock阅读 5,559评论 0 14
  • 9.3.3 快速排序   快速排序将原数组划分为两个子数组,第一个子数组中元素小于等于某个边界值,第二个子数组中的...
    RichardJieChen阅读 1,832评论 0 3
  • 2017.5.19 1、早上户外活动、活动中我应该属于他燃型。 活动要求是集齐大家身上所有物品进行连接、那组最长就...
    Iris_1987阅读 174评论 0 0