数据结构 数组模拟单链表 双链表 栈

用数组模拟链表

1.单链表

  • head模拟头结点;

  • e[ ]存数值,模拟data;

  • ne[ ]存下一个结点的下标,模拟next;

  • 结束用-1表示,模拟NULL。

Subject:
实现一个单链表,链表初始为空,支持三种操作:
​
向链表头插入一个数;
删除第 k 个插入的数后面的数;
在第 k 个插入的数后插入一个数。
现在要对该链表进行 M 次操作,进行完所有操作后,从头到尾输出整个链表。
​
注意:题目中第 k 个插入的数并不是指当前链表的第 k 个数。例如操作过程中一共插入了 n 个数,则按照插入的时间顺序,这 n 个数依次为:第 1 个插入的数,第 2 个插入的数,…第 n 个插入的数。
​
输入格式
第一行包含整数 M,表示操作次数。
​
接下来 M 行,每行包含一个操作命令,操作命令可能为以下几种:
​
H x,表示向链表头插入一个数 x。
D k,表示删除第 k 个插入的数后面的数(当 k 为 0 时,表示删除头结点)。
I k x,表示在第 k 个插入的数后面插入一个数 x(此操作中 k 均大于 0)。
输出格式
共一行,将整个链表从头到尾输出。
​
数据范围
1≤M≤100000
所有操作保证合法。
#include<stdio.h>
​
//e[i]存结点i的数据
//ne[i]存结点i的next指针
//head存头结点的指针域
//idx是当前最新的结点数,即已经用到哪个点了
//-1代表空结点
int e[100009], ne[100009], head, idx;
​
//初始化
void init()
{
     head = -1;//链表最开始指向NULL
     idx = 0;//数组下标从0开始
}
​
//把x插入到头结点
void insert_head(int x)
{
     e[idx] = x;//把x存入
     ne[idx] = head;//把原头结点所在位置给新的,即连接新头结点和旧头结点
     head = idx;//更新头指针地址
     idx++;//指向下一位
}
​
//把x插入到k位后,变成a x a+1
void insert(int x, int k)
{
     e[idx] = x;
     ne[idx] = ne[k];//连接x和a+1
     ne[k] = idx;//连接a和x
     idx++;
}
​
//删除第k个后的数
void remove(int k)
{
     ne[k] = ne[ne[k]];//ne[k]是第k个后的数,即要删除的数;ne[ne[k]]要删除数后的数
     //即实现链表跨越第k个数
}
​
int main()
{
     int m,k,x;
     init();
     scanf("%d", &m);
     while (m--)
     {
          getchar();
          char c;
          scanf("%c", &c);
          if (c == 'H')
          {
               scanf("%d", &x);
               insert_head(x);
          }
          else if (c == 'I')
          {
               scanf("%d%d", &k, &x);
               insert(x,k-1);//数组从0开始
          }
          else
          {
               scanf("%d", &k);
               if (k == 0)//删除头结点
               {
                    head = ne[head];//head直接后移
               }
               else
               {
                    remove(k - 1);//∵数组从0开始,所以要-1
               }
          }
     }
     for (int i = head; i != -1; i = ne[i])//从head开始,依次找下一个数据下标
     {
          printf("%d ", e[i]);
     }
     return 0;
}
​

2.双链表

Subject:
实现一个双链表,双链表初始为空,支持 5 种操作:
​
在最左侧插入一个数;
在最右侧插入一个数;
将第 k 个插入的数删除;
在第 k 个插入的数左侧插入一个数;
在第 k 个插入的数右侧插入一个数
现在要对该链表进行 M 次操作,进行完所有操作后,从左到右输出整个链表。
​
注意:题目中第 k 个插入的数并不是指当前链表的第 k 个数。例如操作过程中一共插入了 n 个数,则按照插入的时间顺序,这 n 个数依次为:第 1 个插入的数,第 2 个插入的数,…第 n 个插入的数。
​
输入格式
第一行包含整数 M,表示操作次数。
​
接下来 M 行,每行包含一个操作命令,操作命令可能为以下几种:
​
L x,表示在链表的最左端插入数 x。
R x,表示在链表的最右端插入数 x。
D k,表示将第 k 个插入的数删除。
IL k x,表示在第 k 个插入的数左侧插入一个数。
IR k x,表示在第 k 个插入的数右侧插入一个数。
输出格式
共一行,将整个链表从左到右输出。
​
数据范围
1≤M≤100000
所有操作保证合法。
  • 初始化

  • 把下标为idx,值为x的新结点插入到k的右端

     

  • 删除下标为k的点

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
​
int m;
int r[100009], l[100009], e[100009],idx;
//r[i]存第i个右边的数的下标
//l[i]存第i个左边的数的下标
//e[i]存第i个数的值
//ixd存当前最新的数,即最新下标
​
//初始化
void init()
{
     idx = 2;//初始时有两个元素
     r[0] = 1;//第一个元素的右端点为1
     l[1] = 0;//第二个元素的左端点为0
}
​
//在k右边插入数 x
void insert(int k, int x)
{
     e[idx] = x;
     r[idx] = r[k];
     l[idx] = k;
     l[r[k]] = idx;
     r[k] = idx;
     idx++;
}
​
//删除第k位的数
void del(int k)
{
     r[l[k]] = r[k];
     l[r[k]] = l[k];
}
​
//输出
void output()
{
     for (int i = r[0]; i != 1; i = r[i])
     {
          printf("%d ", e[i]);
     }
}
​
int main()
{
     int m,x,k;
     scanf("%d", &m);
     init();
     while (m--)
     {
          getchar();
          char c[3];
          scanf("%s", c);
          if (strcmp(c,"L")==0)
          {
               scanf("%d", &x);
               insert(0, x);
          }
          else if (strcmp(c,"R")==0)
          {
               scanf("%d", &x);
               insert(l[1], x);//l[1]代表尾结点左边的数,即最后一个数
          }
          else if (strcmp(c,"D")==0)
          {
               scanf("%d", &k);
               del(k+1);//因为初始化时加了两个结点 数组又从0开始算∴k+2-1
          }
          else if (strcmp(c, "IL")==0)
          {
               scanf("%d%d",&k,&x);
               insert(l[k+1], x);//在第k个插入的数 左结点后插入x
          }
          else
          {
               scanf("%d%d", &k, &x);
               insert(k+1, x);//在k结点后插入
          }
     }
     output();
     return 0;
}

3.栈

  • 栈:先进先出

  • 队列:先进后出

Subject:
实现一个栈,栈初始为空,支持四种操作:
​
push x – 向栈顶插入一个数 x;
pop – 从栈顶弹出一个数;
empty – 判断栈是否为空;
query – 查询栈顶元素。
现在要对栈进行 M 个操作,其中的每个操作 3 和操作 4 都要输出相应的结果。
​
输入格式
第一行包含整数 M,表示操作次数。
​
接下来 M 行,每行包含一个操作命令,操作命令为 push x,pop,empty,query 中的一种。
​
输出格式
对于每个 empty 和 query 操作都要输出一个查询结果,每个结果占一行。
​
其中,empty 操作的查询结果为 YES 或 NO,query 操作的查询结果为一个整数,表示栈顶元素的值。
​
数据范围
1≤M≤100000,
1≤x≤109
所有操作保证合法。
#include<stdio.h>
#include<string.h>
​
int a[100009], k = 0;
​
void pu(int x)
{
     a[k] = x;
     k++;
}
​
void po()
{
     k--;
}
​
void em()
{
     if (k > 0)
     {
          printf("NO\n");
     }
     else
     {
          printf("YES\n");
     }
}
​
void qu()
{
     printf("%d\n", a[k-1]);
}
​
int main()
{
     int m,x;
     scanf("%d", &m);
     while (m--)
     {
          getchar();
          char s[9];
          scanf("%s", s);
          if (strcmp(s, "push") == 0)
          {
               scanf("%d", &x);
               pu(x);
          }
          else if (strcmp(s, "pop") == 0)
          {
               po();
          }
          else if (strcmp(s, "empty") == 0)
          {
               em();
          }
          else
          {
               qu();
          }
     }
     return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值