算法与数据结构(一)

引子:数据结构分为线下结构和非线性结构

数据结构的分类

(一)线性结构

1.数据元素之间存在一对一的线性关系。

2.线性结构有两种不同的存储结构,即顺序存储结构和链式存储结构。顺序存储的线性表称为顺序表,顺序表中的存储结构是连续的。

3.链式存储结构的线性表称为链表,链表中的存储元素不一定是连续的,元素节点中存放数据元素以及相邻元素的地址信息。

4.线性结构常见的有:数组,队列,链表和栈。
 

(二)非线性结构

非线性结构包括:二维数组,多维数组,广义表,树结构,图结构。

稀疏数组

当一个数组中大部分元素为0,或者为同一个值的数组时,可以用稀疏数组来保存该数组。

思路:先记录数组有几行几列,以及用sum变量记录有不用的值(当然这里前提已知了很多相同元素的值为多少) ,再把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模。

例题:五子棋程序中,有存盘退出和续上盘的功能。

代码如下(具体细节部分 看注释   Java代码)

package com.jxust.sparseArray;

public class SparesArray {

    public static void main(String[] args) {
        //创建二维数组 11*11
        // 0 代表没有棋子,1表示黑子 2 表示白子

        int[][] arr1 = new int[11][11];
        arr1[1][2] = 1;
        arr1[2][3] = 2;

        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 11; j++)
                System.out.printf("%d \t", arr1[i][j]);
            System.out.println();
        }

        //数组有多少个非0数
        int sum = 0;
        for (int i = 0; i < 11; i++)
            for (int j = 0; j < 11; j++) {
                if (arr1[i][j] != 0) sum++;
            }


        //赋值稀疏数组
        int cnt = 0;
        int[][] arr2 = new int[sum + 1][3];
        arr2[0][0] = 11;
        arr2[0][1] = 11;
        arr2[0][2] = sum;
        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 11; j++) {
                if (arr1[i][j] != 0) {
                    cnt++;
                    arr2[cnt][0] = i;
                    arr2[cnt][1] = j;
                    arr2[cnt][2] = arr1[i][j];
                }
            }
        }

        //输出稀疏数组
        System.out.println("==========");
        for (int i = 0; i <= sum; i++) {
            for (int j = 0; j < 3; j++) {
                System.out.printf("%d ", arr2[i][j]);
            }
            System.out.println();
        }


        //恢复原始数组
        System.out.println("=================");
        int[][] arr3=new int[ arr2[0][0] ][ arr2[0][1] ];
        for (int i=1; i<arr2.length;i++)
            arr3[ arr2[i][0] ][ arr2[i][1]]=arr2[i][2];

        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 11; j++)
                System.out.printf("%d \t", arr1[i][j]);
            System.out.println();
        }

    }

    }


单链表

定义:每个节点只含有一个指针域的链式结构称为单链表 (下面用数组进行模拟  C++代码)

1. 单链表
// head存储链表头,e[]存储节点的值,ne[]存储节点的next指针,idx表示当前用到了哪个节点  就相当于用数组代替指针执行操作


int head, e[N], ne[N], idx;

// 初始化
void init()
{
    head = -1;
    idx = 0;
}

// 在链表头插入一个数a
void insert(int a)
{
    e[idx] = a, ne[idx] = head, head = idx ++ ;
}

// 将头结点删除,需要保证头结点存在
void remove()
{
    head = ne[head];
}
 

例题 (ACWing 826):

实现一个单链表,链表初始为空,支持三种操作:

  1. 向链表头插入一个数;
  2. 删除第 kk 个插入的数后面的数;
  3. 在第 kk 个插入的数后插入一个数。

现在要对该链表进行 MM 次操作,进行完所有操作后,从头到尾输出整个链表。

注意:题目中第 kk 个插入的数并不是指当前链表的第 kk 个数。例如操作过程中一共插入了 nn 个数,则按照插入的时间顺序,这 nn 个数依次为:第 11 个插入的数,第 22 个插入的数,…第 nn 个插入的数。

输入格式

第一行包含整数 MM,表示操作次数。

接下来 MM 行,每行包含一个操作命令,操作命令可能为以下几种:

  1. H x,表示向链表头插入一个数 xx。
  2. D k,表示删除第 kk 个插入的数后面的数(当 kk 为 00 时,表示删除头结点)。
  3. I k x,表示在第 kk 个插入的数后面插入一个数 xx(此操作中 kk 均大于 00)。

输出格式

共一行,将整个链表从头到尾输出。

数据范围

1≤M≤1000001≤M≤100000
所有操作保证合法。

输入样例:

10
H 9
I 1 1
D 1
D 0
H 6
I 3 6
I 4 5
I 4 5
I 3 4
D 6

输出样例:

6 4 6 5

#include<iostream>
using namespace std;

const int N=100010;

int head,e[N],ne[N],idx;
//head 头结点的下标
//e[i]表示结点i的值
//ne[i]表示节点i的next指针是多少
//idx当前用到的点

//初始化
void init(){
    head=-1;
    idx=0;
}

//将x插入到头节点
void add_to_head(int x)
{
    e[idx]=x;
    ne[idx]=head;
    head=idx;
    idx++;
}


//将x插到k节点后面
void add(int k,int x){
    e[idx]=x;
    ne[idx]=ne[k];
    ne[k]=idx;
    idx++;
}

//删除k后面的点
void remove(int k){
    ne[k]=ne[ne[k]];
}

int main(){
    
int m;   cin>>m;

init();



     while (m--){
         
         int k,x; char c;
         cin>>c;
         
         if(c=='H'){
             cin>>x;
             add_to_head(x);
             
         }
         
        else if(c=='D'){
             cin>>k;
             if(!k) head=ne[head];
             else remove(k-1);
         }
         
         else{
             cin>>k>>x;
             add(k-1,x);
         }
         
         
         
      }

         for(int i=head;i!=-1;i=ne[i]) cout<<e[i]<<' ';    
}
v

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值