首页 > 其他分享 >数据结构-顺序表

数据结构-顺序表

时间:2023-10-27 22:04:40浏览次数:33  
标签:顺序 int sq 元素 mid ++ 数组 数据结构

一、概念

1.顺序存储

顺序存储结构,是指用一段地址连续的存储单元依次存储线性表的数据元素

2.存储方式

在编程语言中,用一维数组来实现顺序存储结构,在C语言中,把第一个数据元素存储到下标为0的位置中,把第 2 个数据元素存储到下标为 1 的位置中,以此类推。

3.长度和容量

数组的长度指的是数组当前有多少个元素,数组的容量值的是数字最大能存放多少个元素,数组越界就是因为超过了自己申请的数组的最大容量

4.数据结构定义

#define DataType int        // (1)
struct SeqList {
    DataType data[MAXN];    // (2)
    int length;             // (3)
};

(1)数组类型为DataType,定义为int;

(2)SeqList定义的就是一个最多存放MAXN个元素的数组,MAXN代表数组容量;

(3)length代表数组长度,即当前的元素个数

二、常用接口实现

1.只读接口(帮助理解)

(1)索引

索引就是通过数组下标寻找数组元素的过程

DataType SeqListIndex(struct SeqList *sq, int i) {

    return sq->data[i];          // (1)i的取值必须为非负整数

}

索引的算法时间为O(1)

(2)查找

通过数组元素寻找数组下标的过程

DataType SeqListFind(struct SeqList *sq, DataType dt) {

    int i;

    for(i = 0; i < sq->length; ++i) { // (1)遍历数组

        if(sq->data[i] == dt) {

            return i;                 // (2)找到了,返回下标

        }    

    }

    return -1;                        // (3)没找到,返回-1

}

(3)获取长度

获取 数组的长度 指的是查询当前有多少元素。可以直接用结构体的内部变量。C语言代码实现如下:

DataType SeqListGetLength(struct SeqList *sq) {

    return sq->length;  
}

2.可写接口

(1)插入

在数组的第K个元素前插入一个数V,因为数组是连续存储的,那么从K开始的所有元素都得往后移一位,给插入的元素V腾出一个空间,那么当K=0时,所有元素都得移动,所有最坏的时间复杂度为O(n).

C语言代码实现如下:

int SeqListInsert(struct SeqList *sq, int k, DataType v) {

    int i;

    if(sq->length == MAXN) {

        return 0;                        // (1)当元素个数已经满的时候,说明无法再插入了
    }  
    for(i = sq->length; i > k; i--) {

        sq->data[i] = sq->data[i-1];     // (2)从该数组的最后一位往后移动,一直到第K位也后移一位
    }

    sq->data[k] = v;                     // (3) 将第K位数变成V 
    sq->length ++;                       // (4) 数组长度加一
    return 1;                            // (5)  返回1代表插入成功
}

数据结构-顺序表_数组

(2)删除

将数组的第K个元素删除,因为数组存储是连续的,那么第K个元素删除,往后的元素势必要往前移动一位,当K=0时,所有元素都得移动,所以最坏时间复杂度为O(n)

C语言代码实现如下:

 int SeqListDelete(struct SeqList *sq, int k) {

    int i;

    if(sq->length == 0) {

        return 0;                        // (1)  返回0代表失败
    }  
    for(i = k; i < sq->length - 1; ++i) {

        sq->data[i] = sq->data[i+1];     // (2) 从前往后覆盖
    }  
    sq->length --;                       // (3)  数组长度减一
    return 1;                            // (4)  返回1代表删除成功

}

数据结构-顺序表_数据结构_02

三、优缺点

1.优点

(1)无须为表示表中元素逻辑关系而增加额外的存储空间

(2)随机存取元素时可以达到O(1),效率高

2.缺点

(1)插入和删除时需要移动大量元素

(2)必须一开始就确定存储空间的容量

四、数组相关算法

1、线性枚举

(1)问题描述

给定一个长度为 n(1≤n≤105) 的整型数组,求所有数组元素中的其中的最小值

(2)算法描述

遍历数组,进行条件判断,条件满足则执行逻辑。这里的条件就是 枚举到的数 是否小于 当前最小值,执行逻辑为 将 当前枚举到的数 赋值给 当前最小值;

代码示例如下:

int findMin(int* nums, int numsSize){

    int min = 100000;

    for(int i = 0; i < numsSize; ++i) {     // (1)从第一个元素开始遍历

        if(nums[i] < min) {             // (2)如果当前枚举到的数小于记录的变量min,则将它赋值给min

            min = nums[i];

        }

    }

    return min;                         // (3)拿到的就是该数组中最小的数

}

2、前缀和差分

(1)问题描述

给定一个 n(n≤105) 个元素的整型数组 ai,再给出 m(m≤105)次询问,每次询问是一个区间 [l,r],求 h(l,r)=∑rk=lak

(2)算法描述

第一个枚举,利用一个数组sum,存储前i个元素的和

第二个枚举,读入m 组数据 l,r,对每组数据,通过 O(1)获取答案,即 sumr-suml-1

代码示例如下:

int sum[maxn];

int* prefixSum(int* nums, int numsSize, int m, int *l, int *r){

    int i;

    int *ret;

    for(i = 0; i < numsSize; ++i) {

        sum[i] = nums[i];

        if(i)  
            sum[i] += sum[i-1];                 // (1)  计算前缀和
    }

    ret = (int *) malloc( m * sizeof(int) );    // (2)  需要返回的数组
    for(i = 0; i < m; ++i) {

    	int leftsum = l[i]==0? 0 : sum[l[i]-1]; // (3)  为了防止数组下标越界
    	int rightsum = sum[r[i]];

    	ret[i] = rightsum - leftsum;            // (4)  差分计算
    }

    return ret;

}

数据结构-顺序表_数组_03

3、双指针

(1)问题描述

给定一个长度为 n(1≤n≤107)的字符串 s,求一个最长的满足所有字符不重复的子串。

(2)算法描述

 如上文所述,这种利用问题特性,通过两个指针,不断调整区间,从而求出问题最优解的算法就叫 “尺取法”,由于利用的是两个指针,所以又叫 “双指针” 算法。

  这里 “尺” 的含义,主要还是因为这类问题,最终要求解的都是连续的序列(子串),就好比一把尺子一样,故而得名。

算法描述如下:

  (1)初始化 数据结构-顺序表_数组_04, 数据结构-顺序表_数组_05,代表一开始 “尺子” 的长度为 0;

(2)增加 “尺子” 的长度,即 数据结构-顺序表_算法_06

   (3)判断当前这把 “尺子” 数据结构-顺序表_算法_07 是否满足题目给出的条件:

    (3.a)如果不满足,则减小 “尺子” 长度,即 数据结构-顺序表_数据结构_08,回到 (3);

    (3.b)如果满足,记录最优解,回到 (2);

核心算法就是:满足条件,j++,反之,i++

代码示例如下:

int getmaxlen(int n, char *str, int& l, int& r) {

    int ans = 0, i = 0, j = -1, len;   // (1)初始化

    memset(h, 0, sizeof(h));           // (2)h代表的是一个哈希表,memset是初始化哈希
												哈希表记录的是当前枚举的区间S[i,j]中每个字符的个数	
    while (j++ < n - 1) {              // (3)j往右移动

        ++h[ str[j] ];                 // (4)在哈希表中记录字符的个数

        while (h[str[j]] > 1) {      // (5)当h[str[j]] > 1时,说明出现了重复字符串str[j]
											左端点i开始右移,直到没有重复字符为止
            --h[ str[i] ];

            ++i;

        }

        len = j - i + 1;              

        if(len > ans)                  // (6)len = j - i + 1;记录当前最优解的长度,更新

            ans = len, l = i, r = j;

    }

    return ans;

}

4、二分枚举

(1)问题描述

给定一个 n(n≤106)个元素的有序整型数组和一个 target值,求在 O(log2n) 的时间内找到值为 target 的整型的数组下标,不存在则返回 -1。

(2)算法描述

(a)初始情况下,令右端点r=n-1;左端点l=0;

(b)生成一个中间值mid = (r+l)/2;

(b.1)目标等于mid,返回mid;

(b.2)目标元素大于mid, l=mid+1;

(b.3)目标元素小于mid, r=mid-1;

(c)当l>r的时候,则说明没有找到目标值,返回-1,否则,回到b,继续迭代

代码示例如下:

int search(int *nums, int numsSize, int target) {

    int l = 0, r = numsSize - 1;         // (1)初始化l,r

    while(l <= r) {                      // (2) 一直迭代左右区间的端点,直到左端点大于右端点结束

        int mid = (l + r) >> 1;          // (3)中间点

        if(nums[mid] == target) {    
            return mid;                  // (4)找到目标,返回下标mid

        }else if(target > nums[mid]) {

            l = mid + 1;                 // (5)左端点移动到 mid+1

        }else if(target < nums[mid]) {

            r = mid - 1;                 // (6)右端点移动到 mid-1

        }

    }

    return -1;                           // (7)找不到给定值,返回-1

}

5、三分枚举

三分枚举 类似 二分枚举 的思想,也是将区间一下子砍掉一块基本完全不可能的块,从而减小算法的时间复杂度。只不过 二分枚举 解决的是 单调性 问题。而 三分枚举 解决的是 极值问题。

6、插入排序

(1)问题描述

给定一个n个元素的数组,数组下标从0开始,采用插入排序将数组升序排列

(2)算法描述

 (1) 循环迭代变量 数据结构-顺序表_数组_09

 (2) 每次迭代,令 数据结构-顺序表_算法_10数据结构-顺序表_数组_05,循环执行比较 数据结构-顺序表_算法_12数据结构-顺序表_数据结构_13,如果产生 数据结构-顺序表_算法_14 则执行 数据结构-顺序表_数组_15。然后执行 数据结构-顺序表_算法_06,继续执行 (2);否则,跳出循环,回到 (1)

示例代码如下:

void InsertSort(int n, int *a) {    

    int i, j;  
    for(i = 1; i < n; ++i) {

        int x = a[i];                  // (1)认为前i-1个数都是排好序的,令x=a[i]

        for(j = i-1; j >= 0; j--) 
        {    							// (2)逆序的枚举所有已经排好序的数

            if(x <= a[j])、
            {            					// (3)枚举的数大于插入的数x,则当前数后移一个位置

                a[j+1] = a[j];        

            }else

                break;                 // (4)否则跳出循环

        }

        a[j+1] = x;                    // (5)将x插入到合适的位置

    }

}

7、选择排序

(1)问题描述

给定数据结构-顺序表_数据结构_17 个元素的数组,数组下标从 数据结构-顺序表_算法_18 开始,采用「 选择排序 」将数组按照 「升序」排列

(2)示例代码

void Swap(int *a, int *b) {

    int tmp = *a;

    *a = *b;

    *b = tmp;

}
void SelectionSort(int n, int *a) {  
    int i, j;
    for(i = 0; i < n - 1; ++i) {     
        int min = i;                 // (1)记录最小值下标
        for(j = i+1; j < n; ++j) {   // (2)开始遍历,min下标对应的数组的值为最小
            if(a[j] < a[min]) {
                min = j;             
            }
        }
        Swap(&a[i], &a[min]);        // (3)第i个元素个最小的元素进行交换 
    }
}

数据结构-顺序表_数据结构_19

8、冒泡排序

void MaoPao(int n,int *a)
{
    for(int i=0;i<n-1;i++)
    {
      for(int j=0;j<n-1-i;j++)
      {
          if(a[j]<a[j+1])
          {
          	int temp = a[j];
          	a[j] = a[j+1];
          	a[j+1] = temp;
          }
      }
    }

}

时间复杂度为O(n2)


标签:顺序,int,sq,元素,mid,++,数组,数据结构
From: https://blog.51cto.com/u_15858858/8062681

相关文章

  • CF练习题16 (毒瘤数据结构)
    Lomsatgelral把树拍成一条链,询问子树等于询问区间。这样一看这道题就非常莫队。但是有要求个数最多的颜色的编号,我们可以用线段树动态维护颜色的最大值。这样,一个无脑莫队线段树的暴力就做出来了。intn,a[N];intdfn[N],nfd[N],cnt;intb[N],siz[N];vector<int>g[N];in......
  • 队列数据结构实现
    1#include<iostream>2#include<fstream>3usingnamespacestd;45//顾客信息6structInform7{8intArrival;9intTyped;10intHandleTime;11intRestTime;12};1314//链式存储15structComsumer16......
  • 过滤器执行顺序
    请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器:排序的规则是什么呢?每一个过滤器都必须指定一个int类型的order值,order值越小,优先......
  • 数据结构与算法-基本概念
    什么是数据结构与算法从广义上讲数据结构就是指一组数据的存储结构。算法就是操作数据的一组方法。从狭义上讲,是指某些著名的数据结构和算法,比如队列、栈、堆、二分查找、动态规划等。这些都是前人智慧的结晶,我们可以直接拿来用......
  • 解锁高效检索技能:掌握MySQL索引数据结构的精髓
    (文章目录)......
  • pytest设置随机执行case 顺序
    1.安装包  pytest-randomly(这个能成)2. 在class上设置  @pytest.mark.random_orderclassTestMulit:3.设置每条case执行的次数@pytest.mark.repeat(set_ratio.multiple_01)#设置该条case执行的次数这个次数顺序也是混合到总数中的随机执行@allure.title......
  • 【数据结构】- 平衡树
    平衡树简介平衡树是可以维护权值信息的数据结构。平衡树通过对二叉搜索树树高的平衡调整优化插入、删除、修改和查找的复杂度。故而节点其实形成了一个二叉树的形态,通过特定函数支持了查询序列中元素的前驱/后继,排名和特定排名的元素等有关权值的信息。根据平衡树结构特性,也......
  • 数据结构学习2
    三、递归3.1、时空间复杂度   3.2、递归式 ......
  • SQL Server数据结构
    文件类型一个数据库有三种类型的文件:PrimaryFile:.mdf,masterdatafile,记录了这个DB其它文件的指针,每个数据库都有SecondaryFile:默认情况下,数据存在主文件,如果决定对主文件进行扩展,可以创建二级文件,后缀名为.ndfTransactionLogFile:.ldf,每个DB都得有Filegroups便于对......
  • vue学习笔记之执行顺序
       vue文件加载顺序:index.html>app.vue>main.js     加载顺序详情:执行index.html(index.html中id为app的div标签是一个挂载点,之后我们的Vue根实例就会挂载到该挂载点上)执行main.jsmain.js找到实例挂载app.vue文件,将index.html的挂载的内容显示出来(用app.vue的template......