zoukankan      html  css  js  c++  java
  • 基础和线性表

    1 数据结构

      解决问题方法的效率,跟数据的组织方式有关

      解决问题方法的效率,跟空间的利用效率有关

      解决问题方法的效率,跟算法的巧妙程度有关

      数据结构

        数据对象在计算机中的组织方式

          逻辑结构

          物理存储结构

      数据对象必定与一系列加在其上的操作相关联

      完成这些操作所用的方法就是算法

      抽象数据类型(Abstract Data Type)

        数据类型

          数据对象集

          数据集合相关联的操作集

        抽象: 描述数据类型的方法不依赖与具体实现

          与存放数据的机器无关

          与数据存储的物理结构无关

          与实现操作的算法和编程语言无关

      只描述数据对象集和相关操作集是什么, 并不涉及如何做到的问题

    2 算法

      算法

        一个有限指令集

        接受一些输入(或者没有输入)

        产生输出

        一定在有限步骤之后终止

        每一条指令必须

          有充分明确的目标, 不可以有歧义

          计算机能处理的范围之内

          描述应不依赖于任何一种计算机语言以及具体的实现手段

      判定算法好换的依据-复杂度

      空间复杂度S(n)

      时间复杂度T(n)

      一般来说关注的是最坏情况的复杂度平均复杂度

      复杂度的渐进表示法      

      1 < logn < n <nlogn < n2 <2n < n!

    3 最大子列和

      最大子列和问题就是, 给定一个数字序列, 求其中按顺序截取的子序列和最大的

      1) 算法1, 分三层遍历, 第一层遍历序列, 第二层遍历当前之后的, 第三层计算序列的和

        算法1的具体实现

    def algo_1(my_list):
        max_sum = 0
        size = len(my_list)
        for i in range(size):
            for j in range(i,size):
                current_sum = 0
                for k in range(i,j+1):
                    current_sum += my_list[k]
                if current_sum >= max_sum:
                    max_sum = current_sum
        print(max_sum)

      2) 算法2, 分两层遍历, 第一层遍历, 第二计算值

        具体代码如下

    def algo_2(my_list):
        max_sum = 0
        size = len(my_list)
        for i in range(size):
            current_sum = 0
            for j in range(i,size):
                current_sum += my_list[j]
                if current_sum > max_sum:
                    max_sum = current_sum
        print(max_sum)
    

      3) 算法3, 分而治之

        分而治之实现比较复杂

        基本思想就是, 分成两个部分, 求出左边最大的, 求出右边最大的, 求出跨边界最大的, 三者最大的就是最大的

        算法内容是:

          先中分, 再中分,不断中分

          从最小两个分部开始, 选择最大的值

          在联合就近第二小的选择, 处理跨边界, 从边界出发, 得到向左延续的1格, 2格..求出最大的, 右边也是, 然后两个最大的合在一起就是边界最大

          不断重复直到最后

      4) 算法4, 在线处理

        时间复杂度为o(n), 应该是最快的时间复杂度了

        该算法的特点的可以等待输入就可以获得当前序列的最大子序列, 这也是在线处理的由来

        具体的思路是, 抓住子序列的特点的连续的

        要使得连续序列能够增大, 则部分和应该是正数, 当出现负数和式, 需要舍弃值重新计算序列

        具体实现如下

    def algo_4(my_list):
        max_sum = 0
        current_sum = 0
        size = len(my_list)
        for i in range(size):
            current_sum += my_list[i]
            if current_sum > max_sum:
                max_sum = current_sum
            elif current_sum < 0:
                current_sum = 0
        print(max_sum)
    

    4 线性表

    线性结构最简单的就是线性表

    4.1 多项式的表示

      多项式的主要信息有两个, 一个是x的次数, 一个是对应的系数

      1) 方法1, 数组方式

        数组按照索引的方式, 索引对应x的次数, 系数就存放在对应的数组位置

        优点: 计算十分方便

        缺点: 浪费空间

      2) 方法2: 二维数组方式

        数组里面再存一个数组, 数组里面存放系数和次数

        为了便于计算, 存储的时候要按照次数按顺序存入

        计算方式:

          取出两个多项式的第0项目, 比较系数大小, 如果不相同, 输出大的, 然后获得对应多项式的第1项目, 在比较系数进行运算; 如果相同直接运算输出;

         优点: 不用存储系数为0的项目, 节省空间

      3) 方法3: 使用链表存储

        定义一个结构体, 内容有次数, 系数, 下一个指针

        计算方式同方法2

    4.2 线性表以及顺序存储

      一般来说, 线性表的问题都是有两种方式, 要么是数组, 要么是链表

      线性表: 由类型数据元素构成有序序列的线性结构

        表中元素的个数恒伟线性表的长度

        线性表没有元素时, 称为空表

        表其实位置称为表头, 表结束位置称为表尾

      线性表的ADT表示

        

    4.2.1 线性表的顺序存储实现

      利用数组的连续存储空间顺序存放线性表的各个元素

      使用数组的方式来构建线性表

      数据类型表示

    typedef struct{
    	ElementType Data[MAXSIZE];
    	int Last; 
    }List;
    
    List L,*PtrL;

      线性表的主要操作

      1) 初始化

    List *MakeEmpty(){
    	List *PtrL;
    	PtrL = (List *)malloc(sizeof(List));
    	PtrL->Last = -1;
    	return PtrL;
    }
    

      2) 查找

    int Find(ElementType X, List *PtrL)
    {
    	int i = 0;
    	while( i<=PtrL->Last && PtrL->Data[i]!=X )
    		i++;
    	if( i> PtrL->Last)
    		return -1;
    	else
    		return i;
    }
    

      查找的平均次数是 (n+1)/2

      平均时间性能为 O(n)

      3) 插入

      在第i(1<=i<=n+1)个位置插入元素X

      对应在数据上, 就是插入到索引 i-1 的位置

      需要遵循的是先移动再插入

      实现为

    void Insert(ElementType X, int i, List *PtrL)
    {
    	int j;
    	if(PtrL->Last == MAXSIZE-1){
    		printf("表满了");
    		return ;
    	}
    	if( i < 1 || PtrL->Last+2){
    		printf("位置不合法");
    		return ;
    	}	
    	for(j=PtrL->Last; j>=i-1; j--)
    		PtrL->Data[j+1] = PtrL->Data[j];
    	PtrL->Data[i-1] = x;
    	PtrL->Last++;
    	return;
    }
    

      4) 删除

      删除第i(1<=i<=n)个元素  

      后面的元素依次往前移动

      实现

    void Delete( int i, List *PtrL)
    {
    	int j;
    	if( i <1 || PtrL->Last+1 ){
    		printf("不存在第%d个元素", i);
    		return ;
    	}
    	for( j=1; j<=PtrL->Last; j++)
    		PtrL->Data[j-1] = PtrL->Data[j];
    	PtrL->Last--;
    	return ;
    }
    

      平均移动次数为(n-1)/2

      平均时间性能为O(n)

    4.2.2  线性表的链式存储实现  

      链式存储不需要物理存储上也是相邻存储

      元素之间通过指针来链接

      定义数据结构

    typedef struct Node
    {
    	ElementType Data;
    	struct Node *Next;
    }List;
    List L, *PtrL;
    

      主要的操作实现

      1) 求表长度

    int Length(List *PtrL)
    {
    	List *p = PtrL;
    	int j = 0;
    	while(p){
    		p = p->Next;
    		j++
    	}
    	return j;
    }
    

      时间复杂度为O(n)

      2) 查找

      按照序号查找

    List *FindKth( int K, List *PtrL)
    {
    	List *p = PtrL;
    	int i = 1;
    	while( p != NULL && i < K){
    		p = p->Next;
    		i++;
    	}
    	if( i==K )
    		return p;
    	else
    		return NULL;
    }
    

      按值查找

    List *Find(ElementType X, List *PtrL){
    	List *p = PtrL;
    	while( p!=NULL && p->Data!=X)
    		p = p -> Next;
    	return p;
    }
    

      平均时间复杂度为O(0)

      3) 插入

      在第i-1(1<=i<=n+1)个结点后插入一个值为X的新结点

      插入的步骤

        1) 创建一个新的节点, 用s指向

        2) 找到i-1个节点, 用p执行

        3) 修改指针

    s->Next = p->Next;
    p->Next = s;
    

      顺序不能交换, 不然的话就找不到第i个节点的指针了

      

      4) 删除

      删除第i[1,n]个位置上的节点

      步骤

        1) 找到i-1个节点, 用p指向

        2) 用s指向被删除的节点

    s = p->next;
    

        3) 修改p指针

    p->next = s->next;
    

        4) 释放s的空间

      

    4.2.3 广义表和多重链表

      之前的一元多项式可以用顺序表表示

      如果是二元多项式的话, 就可以同样的先看成是关于x的一元多项式, 然后x的系数是关于y的一元多项式

      

      广义表:

        线性表的推广

        在广义表中元素可能是另一个广义表, 而相对的线性表中就是一个单元素

      

      多重链表

        链表中的节点可能同时隶属于多个链

        多重链表中的节点有多个指针域, 但是不是有多个指针域就是剁成链表, 判断的依据是不是指向自身的

      可以用典型的多重链表-十字链表来存储稀疏矩阵

        只存储非0项, 数据域为: 行, 列, 数值

        每个节点通过两个指针域, 把同行同列串起来, 也就是Right和Down指针

      

      

     

  • 相关阅读:
    MySQL事务隔离级别(InnoDB)
    Kettle连接SQL Server数据库
    jstack分析Java进程信息
    Java对Map集合进行排序
    Java堆分析 jmap+jhat
    Oracle列转行 参数动态传入iBatis使用示例
    Hive UDF函数测试
    test
    《串并行数据结构与算法(SML语言)实验》题解
    educoder SML程序设计题线下编译环境搭建
  • 原文地址:https://www.cnblogs.com/weihuchao/p/6900774.html
Copyright © 2011-2022 走看看