从无到有学算法
吾日三省吾身,今天有写代码乎?🙄
🙄抠门渣男语录:我的果汁分你一半(月亮弯弯 绵绵绵绵缠缠) - 李金源 - 单曲 - 网易云音乐
千年之后的你在哪里:星月神话 - 我觉得我还能再吃点 - 单曲 - 网易云音乐
目录
第一节 解密QQ号--队列
第二节 解密回文--栈
第三节 纸牌游戏--小猫钓鱼
题目
思路 + 代码
完整代码
输入输出
第四节 链表
基础概念
实现链表
完整代码1
插入数据
完整代码2
第五节 模拟链表
先补充个理解:
1,栈中的“先进后出,后进先出”什么意思
栈类似于弹匣,就像装子弹压弹进弹匣一样,一粒一粒压进去,但是退子弹是从最上面开始的,最先压进去的最后弹出来,最后一个压进去的第一个弹出来,这就是“先进后出”,也叫“后进先出”
2,栈的定义
栈就是数据暂时存储的地方,所以才有进栈,出栈的说法
3,栈与队列的区别
栈是把子弹子弹压进弹匣,后进的先出;队列就像排队,你第一个排,那就第一个轮到你,这就是先进先出,也叫后进后出。dfs(深度优先搜索)应用栈,而bfs(广度优先搜索)应用队列。栈占用空间小,而堆中的bfs常用于最短路。
4,栈在计算机领域的解释
栈作为一种数据结构,是只能在一端进行插入和删除的特殊线性表,它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始读。允许进行插入和删除操作的一段称为栈顶(top),另一端称为栈底(bottom)。栈底固定,而栈顶浮动;栈中元素个数为0时成为空栈。插入数据称为进栈(PUSH),删除数据称为退栈(POP),栈也称后进先出表。栈在函数调用时可以可以存储断点,做递归时要用到栈!
5,堆和栈的区别
栈快捷但自由度小,堆过程长但自由度大
第一节 解密QQ号--队列
介绍
队列是一种特殊的线性结构,遵循“先进先出”,First In First Out,FIFO原则
它是BFS(Breadth First Search广度优先搜索)和队列优化的Bellman-Ford最短路算法的核心数据结构
比如排队买票,打电话中的人工服务,都是队列的例子,来的越早的人,越早买到票并离开
队首(head)删除数据,称之为“出队”
队尾(tail)插入数据,称之为“入队”
当队列中没有元素时(head == tail),称为空队列
题目
小哼问小哈QQ号是多少,小哈是个大美女,小哈给了他一串加密后的数字,解密规则是:
先将第1个数删除,然后把第2个数放到这串数末尾,再将第3个数删除,并把第4个数放到末尾......
直到剩下最后一个数,把最后一个数也删除。把删除的数连在一起就是小哈的QQ号了。小哈给他加密过的一串数是“920430714”,求小哈的QQ号是多少?
解析


队首删除一个数的操作是:head++;
队尾增加一个数的操作是:q[tail] = x; tail++;
现在有9个数,把9个数放入队列后,head == 1,tail == 10,此时head和tail之间的数就是目前队列中“有效”的数
代码1
#include<iostream>
using namespace std;
int main()
{
    int q[102] = {0, 9, 2, 0, 4, 3, 0, 7, 1, 4}; //q[0]是额外加上的
    int head = 1, tail = 10; //head指向队首,tail指向队尾下一个位置
    while(head < tail) {//队列不为空
        cout<<q[head]; //打印队首
        head++; //队首出队
        q[tail] = q[head]; //新的队首添加到队尾
        tail++;
        head++; //新队首出队
    }
    return 0;
}
903744102代码2
将队列三个基本元素(一个数组,两个变量)封装为一个结构体类型
代码臃肿(本题不必用结构体),只是为了敲多一遍加深印象
#include<iostream>
using namespace std;
struct que
{
    int a[100]; //队列主体,存储数据
    int head; //队首
    int tail; //队尾
};
int main()
{
    struct que q;
    q.head = 1;
    q.tail = 1;
    for(int i = 1; i <= 9; ++i) {
        cin>>q.a[q.tail]; //在队尾插入数据
        q.tail++;
    }
    while(q.head < q.tail) {//队列不为空
        cout<<q.a[q.head]; //打印队首
        q.head++; //队首出队
        q.a[q.tail] = q.a[q.head]; //新的队首添加到队尾
        q.tail++;
        q.head++; //新队首出队
    }
    return 0;
}
9 2 0 4 3 0 7 1 4
903744102第二节 解密回文--栈
队列先进先出,栈后进先出,生活中的例子有:
1,吃桶装薯片,得先吃完前面的才能吃到最后一片
2,浏览网页退回之前某个网页,需要一步步点击后退键
3,给弹夹装子弹,最后装入的子弹是第一个被打出去的,或者说第一个被退出来的
4,又比如一个小桶,小桶的直径只能放入一个球,依次放入2,1,3号小球,想取出2号球就得先将3号取出来,再将1号取出来,最后才能取最先放进去的2号小球

下面我们用栈的思路判断回文:
只需要一个一维数组a[110]保存读入的数据
一个一维数组s[110]作为栈的主体和一个指向栈顶的变量top就可以
初始化top = 0
入栈的操作:s[++top] = a[i];
通过strlen(a)得到字符串长度len,mid = len / 2 - 1;
代码第14行 s[++top] = a[i]; 为什么用++top呢,为了使后续top = 1(最后一个字符)后,再 top--,即top = 0时可判断为YES
第8行 cin.get(a, 110); 等价于 gets(a),都可读入字符数组的字符串,不过后者头文件为#include<cstdio>,前者头文件为#include<cstring>
#include<iostream>
#include<cstring> //strlen(), cin.get()
using namespace std;
int main()
{
    char a[110], s[110];
    int len, mid, next, top;
    cin.get(a, 110); //读入字符串
    len = strlen(a); //求长度
    mid = len / 2 - 1;
    top = 0;
    for(int i = 0; i <= mid; ++i)
        s[++top] = a[i]; //mid前的字符入栈
    if(len % 2 == 0) next = mid + 1;
    else next = mid + 2; //奇偶匹配的起始下标不一样
    //开始匹配
    for(int i = next; i <= len - 1; ++i) {
        if(a[i] != s[top])
            break;
        top--;
    }
    if(top == 0) cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
    return 0;
}
aininia
YES
nihuai
NO下面是不用栈的思路,它需要一个数组a和两个变量left, right
#include<iostream>
#include<cstring> //cin.get(), strlen()
using namespace std;
char a[666];
bool repeat(int left, int right) //判断回文
{
    int flag = 1;
    while(left < right) {
        if(a[left++] == a[right--]) continue;
        else flag = 0; //出现不相等
    }
    return flag;
}
int main()
{
    cin.get(a, 666);
    int right = strlen(a) - 1;
    if(repeat(0, right)) 
        cout<<"YES"<<endl;
    else
        cout<<"NO"<<endl;
    return 0;
}
bananab
YES
bababb
NO栈还可验证括号匹配,end~
第三节 纸牌游戏--小猫钓鱼
本题结合了栈和队列
我们需要两个队列,一个栈来模拟整个游戏
题目
寒假到了,小哼和小哈出来约会,他们来到了一家咖啡馆玩桌游。
这款桌游是一个叫“小猫钓鱼”的扑克游戏:
1,
将一份扑克牌平均分两份,每人一份。小哼先拿出了自己手中的第一张扑克牌放到桌上,然后小哈也拿出自己受手中的第一张扑克牌,并放在小哼刚打出的扑克牌上面,就像这样两人交替出牌
2,
出牌时,如果某人打出的牌与桌上某张牌牌面相同,即可将两张相同的牌及中间所夹的牌全部取走,并依次放到自己手中牌的末尾
3,
当任意一人手中的牌全部出完,游戏结束,对手获胜,
假设游戏开始,小哼有6张牌,小哈也有6张,且牌的牌面只有1~9
思路 + 代码
(以下思路中,存在游戏永远无法结束的情况,只是简陋版本)
容易得知,胜负从拿到牌开始就确定了,且桌上每种牌面最多一张
创建一个结构体来实现队列
struct queue
{
    int data[1000];
    int head;
    int tail;
};head存储队首,tail存储队尾,数组data存储队列元素,当然大小的设置可以不止1000,数组不越界就好
创建一个结构体来实现栈
struct stack
{
    int data[10];
    int top;
};top存储栈顶,数组data存储栈元素,大小设为10,因为只有9种不同牌面,考虑到打出的牌与桌面相同则可取走,桌上最多只能有9张牌,所以10够用了
定义队列变量q1, q2,q1模拟小哼的牌,q2模拟小哈的牌,定义栈变量s模拟桌上的牌
struct queue q1, q2;
struct stack s;初始化队列和栈
//初始化q1, q2为空,此时小哼小哈手中无牌
q1.head = 1; q1.tail = 1;
q2.head = 1; q2.tail = 1;
//初始化栈s为空,最开始桌上无牌
s.top = 0;分别读入小哼,小哈的牌,每次读入6个数,分别插入q1, q2
for(int i = 1; i <= 6; ++i) {
    cin>>q1.data[q1.tail]; //读入一个数到队尾
    q1.tail++; //队尾往后挪一位
}
for(int i = 1; i <= 6; ++i) {
    cin>>q2.data[q2.tail]; 
    q2.tail++;
}小哼出牌
t = q1.data[q1.head]; //小哼亮出一张牌小哼打出第一张牌,即q1队首,将这张牌存放在临时变量t种,接下来判断桌上有无与t相同的牌
用一个数组记录桌上的牌,由于牌面只有1~9,开一个大小为10的数组即可
int book[10];将book[1]~book[9]初始化为0,因为开始桌上无牌
for(int i = 0; i <= 9; ++i)
    book[i] = 0;如果桌上多了一张牌面2的牌,则book[2] = 1,因为牌面为2的牌桌上有了。若牌面2的牌被拿走,就将book[2]设置为0,表示桌上没有牌面2的牌了,此时只需一个if来判断桌上是否有某张牌(类似桶排序)
t = q1.data[q1.head]; //小哼先出牌
if(book[t] == 0) { //桌面没有牌面为t的牌,小哼本轮没有赢牌
    q1.head++; //已打出的牌出队
    s.top++; //注意top初始为0
    s.data[s.top] = t; //已打出的牌入栈,即放到桌面
    book[t] = 1; //标记桌上有牌面t的牌
}如果不满足book[t] == 0,小哼可以赢得桌上的牌,将赢得的牌依次放入小哼手中
else {
    q1.head++; //小哼已出牌,所以要把这张牌出队
    q1.data[q1.tail] = t; //可赢牌,就把刚打出的牌放回手中牌的末尾
    q1.tail++;
    while(s.data[s.top] != t) { //桌上可赢的,依次放到手中末尾
        q1.data[q1.tail] = s.data[s.top]; //依次放入队尾
        q1.tail++;
        s.top--; //栈种少了一张牌,栈顶减1
    }
}以上,就是小哼出牌阶段,小哈类似,只是q1变q2
在模拟两人出牌外,加一个while循环判断是否有人出完牌
while(q1.head < q1.tail && q2.head < q2.tail) 
//队列q1, q1都不为空,双方都有牌,继续循环最后,输出winner,以及获胜者手中的牌 和 桌上的牌
若小哼获胜,小哈手中无牌,此时q2.head == q2.tail
if(q2.head == q2.tail) {
    cout<<"小哼win"<<endl;
    cout<<"小哼当前手中的牌是";
    for(i = q1.head; i <= q1.tail - 1; ++i)
        cout<<q1.data[i];
    cout<<endl;
    if(s.top > 0) {//若桌上有牌,依次输出
        cout<<"桌上的牌是";
        for(i = 1; i <= s.top; ++i)
            cout<<s.data[i];
        cout<<endl;
    }
    else
        cout<<"桌上已经没有牌了"<<endl;
}完整代码
#include<iostream>
using namespace std;
struct queue
{
    int data[1000]; //队列的主体,表示玩家的牌
    int head; //队首
    int tail; //队尾
};
struct stack
{
    int data[10]; //栈的主体,表示桌上的牌
    int top; //栈顶
};
int main()
{
    struct queue q1, q2; //队列变量
    struct stack s; //栈变量
    int book[10];
    int i, t;
    //初始化队列
    q1.head = 1; q1.tail = 1;
    q2.head = 1; q2.tail = 1;
    //初始化栈
    s.top = 0;
    //初始化标记桌上牌的数组
    for(i = 1; i <= 9; ++i)
        book[i] = 0;
    //依次向队列插入小哼的6张牌
    for(i = 1; i <= 6; ++i) {
        cin>>q1.data[q1.tail];
        q1.tail++;
    }
    //依次向队列插入小哈的6张牌
    for(i = 1; i <= 6; ++i) {
        cin>>q2.data[q2.tail];
        q2.tail++;
    }
    while(q1.head < q1.tail && q2.head < q2.tail) { //队列不为空
        t = q1.data[q1.head]; //小哼出的第一张
        //判断当前能否赢
        if(book[t] == 0) {//桌上没有这个牌面的牌
            q1.head++; //打出的牌出队
            s.top++;
            s.data[s.top] = t; //打出的牌入栈
            book[t] = 1; //标记桌上有了牌面t的牌
        }
        else { //桌上有这个牌
            q1.head++; //已打出的出队
            q1.data[q1.tail] = t; //打出的牌放到末尾
            q1.tail++;
            while(s.data[s.top] != t) {//可赢的牌
                book[s.data[s.top]] = 0; //取消标记
                q1.data[q1.tail] = s.data[s.top]; //依次放入队尾
                q1.tail++;
                s.top--; //桌上少了一张,栈顶减1
            }
            //遇到牌面与打出一样的,跳出上面的while
            book[s.data[s.top]] = 0;
            q1.data[q1.tail] = s.data[s.top];
            q1.tail++;
            s.top--;
        }
        if(q1.head == q1.tail) break; //牌出完,游戏结束
        t = q2.data[q2.head]; //小哈出的第一张
        //判断当前能否赢
        if(book[t] == 0) {//桌上没有这个牌面的牌
            q2.head++; //打出的牌出队
            s.top++;
            s.data[s.top] = t; //打出的牌入栈
            book[t] = 1; //标记桌上有了牌面t的牌
        }
        else { //桌上有这个牌
            q2.head++; //已打出的出队
            q2.data[q2.tail] = t; //打出的牌放到末尾
            q2.tail++;
            while(s.data[s.top] != t) {//可赢的牌
                book[s.data[s.top]] = 0; //取消标记
                q2.data[q2.tail] = s.data[s.top]; //依次放入队尾
                q2.tail++;
                s.top--;
            }
            //遇到牌面与打出一样的,跳出上面的while
            book[s.data[s.top]] = 0;
            q2.data[q2.tail] = s.data[s.top];
            q2.tail++;
            s.top--;
        }
    }
        if(q2.head == q2.tail) {
            cout<<"小哼win"<<endl;
            cout<<"小哼当前手中的牌是 ";
            for(i = q1.head; i <= q1.tail - 1; ++i)
                cout<<q1.data[i]<<" ";
            cout<<endl;
            if(s.top > 0) { //桌上有牌就输出
                cout<<"桌上的牌是 ";
                for(i = 1; i <= s.top; ++i)
                    cout<<s.data[i]<<" ";
            }
            else
                cout<<"桌上已经没有牌了"<<endl;
        }
        else {
            cout<<"小哈win"<<endl;
            cout<<"小哈当前手中的牌是 ";
            for(i = q2.head; i <= q2.tail - 1; ++i)
                cout<<q2.data[i]<<" ";
            cout<<endl;
            if(s.top > 0) { //桌上有牌就输出
                cout<<"桌上的牌是 ";
                for(i = 1; i <= s.top; ++i)
                    cout<<s.data[i]<<" ";
            }
            else
                cout<<"桌上已经没有牌了"<<endl;
        }
    return 0;
}
输入输出
2 4 1 2 5 6
3 1 3 5 6 4
小哈win
小哈当前手中的牌是 1 6 5 2 3 4 1
桌上的牌是 3 4 5 6 2
1 6 2 8 5 5
3 4 6 7 3 2
小哈win
小哈当前手中的牌是 2 6 2 4 6 3 5 7 8 3
桌上的牌是 1 5
7 8 9 1 2 3
6 4 2 3 3 8
小哼win
小哼当前手中的牌是 3 3 2 4 1 9 3 8 2
桌上的牌是 7 6 8跟着书本敲完一遍,好像学到了什么,又好像什么都没学到 🙄(只能说有了印象,大概理解)
由于是简陋版本,只能通过部分测试数据,这个程序显然是不够“健壮”的
第四节 链表
只通过啊哈算法里讲的那一点点,是不够的,所以我通过网上的资源加深理解
要善用网上资源,网络不是只让你打游戏,撩妹😂,娱乐的
1,blibli(1.5倍速) (40分钟)
1个小时学会单链表,C语言数据结构专题_哔哩哔哩_bilibili
2,blibli(1.5倍速) (15分钟)
2.4链表_哔哩哔哩_bilibili
3,CSDN(30分钟) 链表基础知识详解(非常详细简单易懂)_不秃也很强的博客-CSDN博客_链表
然后我开始结合自己的理解,照着书本敲关键知识点(90分钟)
基础概念
1,
链表由一个个节点构成,每个节点采用结构体的形式组织,它是一种物理存储上非连续,通过指针连接的线性存储结构
2,
链表与数组的区别:
数组通过开辟连续的内存来存储数据,有起始和结束地址;
而链表通过对节点的插入和删除实现对数据的读取,没有头尾之分
使用链表可以更灵活地对数据进行插入和删除
3,
链表由结构体变量(节点)相连构成,每一个节点由数据域和指针域组成,数据域存放具体数值,指针域存放下一节点首地址
4,
结构体中的"."和"->"可以读作“的”,比如p->next读作p的next,p->data读作p的data,用来访问结构体成员,区别是,指针变量用"->",一般变量用"."访问成员
实现链表
如何实现链表呢?使用指针和动态分配内存函数malloc来实现
指针:
指针中的 * 表示取内容或者说解引用,& 表示取地址,比如
int a; cin>>a; int *p; p = &a; cout<<*p;
&将a变量的地址赋值给指针p,指针p表示a变量的地址
*使p取得a所指向地址的值,*p表示a变量的地址所指向的值
malloc函数:(头文件#include<cstdlib>)
1,malloc(sizeof(int))
等价于 malloc(4); 从内存中申请分配4个字节大小的内存空间
2,
现在已经成功从内存中申请了4个字节的空间来存放一个整数,如何对这个空间操作呢?
这就需要一个指针来指向这个空间,即存储这个空间的首地址
3,(int *)
malloc()函数返回类型使void *类型,表示未确定类型的指针,该类型可强制转换为任何其他类型指针,此处我们需要强转整型,所以是(int *)
int *p; //定义指针p
p = (int *)malloc(sizeof(int));malloc()函数动态申请空间:
#include<iostream>
#include<cstdlib> //malloc()
using namespace std;
int main()
{
    int *p; //定义指针p
    //指针p获取动态分配的内存地址
    p = (int *)malloc(sizeof(int));
    *p = 10; //向p所指向的内存存入10
    cout<<*p<<endl; //输出p指向内存中的值
    return 0;
}
10每一个节点由两部分组成,左边部分存放具体数值,右边部分存储下一个节点的地址(称为后继指针),这里我们定义一个结构体类型来存储这个节点

struct node //节点node
{
    int data; //数据域
    struct node *next; //指针域,存放下一节点首地址
}; 
 
上面代码中,我们定义了一个叫node的结构体类型,它有俩成员,第一个成员叫data,用来存储具体的数值;第二个成员是一个指针,用来存储下一节点的地址。因为下一节点的类型也是struct node,所以这个指针的类型也必须是struct node *类型的指针。
如何建立链表呢?首先需要一个头指针head指向链表的最开始,链表未建立时头指针为空(可理解为指向空节点)
struct node *head;
head = NULL; //头指针初始为空现在创建第一个节点,并用临时指针p指向这个节点
struct node *p;
p = (struct node *)malloc(sizeof(struct node));
//使指针p变成了结构体变量设置第一个节点的左半部分和右半部分
int a;
cin>>a;
p->data = a; //将a的值存储到节点的数据域中
p->next = NULL; //后继指针为空,即下一节点为空 
可以这样念“p的data等于a,p的next为空”,->是结构体指针运算符,用来访问内部成员
设置头指针:(方便从头遍历整个链表)
1,如果这是第一个创建的节点,头指针指向这个节点
2,如果不是,上一节点的后继指针指向这个节点
 
if(head == NULL)
    head = p; //第一个节点被头指针指向
else
    q->next = p; //否则上一节点后继指针指向这里最后将指针p也指向当前节点,因为下一步临时指针p会指向新节点
q = p; //指针q指向当前节点完整代码1
#include<iostream>
#include<cstdlib> //malloc()
using namespace std;
struct node
{
    int data;
    struct node *next;
};
int main()
{
    struct node *head, *p, *q, *t;
    int i, n, a;
    cin>>n;
    head = NULL; //头指针初始为空
    for(i = 1; i <= n; ++i) {
        cin>>a;
        //动态申请一个空间存放节点,临时指针p指向这个节点
        p = (struct node *)malloc(sizeof(struct node));
        p->data = a; //数据存储到数据域
        p->next = NULL; //后继指针指向空
        if(head == NULL)
            head = p; //第一个节点让头指针指向
        else
            q->next = p; //否则上一节点后继指针指向当前节点
        q = p; //上一节点指针指向当前节点
    }
    //输出链表中所有数
    t = head;
    while(t != NULL) {
        cout<<t->data<<" ";
        t = t->next; //继续下一节点
    }
    return 0;
}
9
2 3 5 8 9 10 18 26 32
2 3 5 8 9 10 18 26 32注意,上述代码没有free(释放动态申请的空间),很不安全
插入数据
接下来,往链表插入6
 
关于插入,这里有个关键:
下方完整代码第38,39行,初始指针t指向5,p指向6,t的next指向8
-  p->next = t->next; 
-  t->next = p; 
这两步相当于链表断开,接上了一个新的元素
p的next指向原来的t的next(指向了8的地址)
t的next再指向p的地址,顺序不能调换
插入后,t的next指向p的地址,p的next指向8的地址
首先用临时指针t从链表头部开始遍历
t = head; //从链表头部开始遍历等指针t下一节点的值比6大,将6插到两节点中间,即t->next->data大于6时插入
t->next->data跟我念“t的next的data”
cin>>a; //读入待插入的数
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; //继续下一节点
}完整代码2
#include<iostream>
#include<cstdlib> //malloc()
using namespace std;
//创建一个结构体表示节点
struct node
{
    int data;
    struct node *next;
};
int main()
{
    struct node *head, *p, *q, *t; //p,q,t都是临时指针
    int i, n, a;
    cin>>n; //n个数
    head = NULL; //头指针初始为空
    for(i = 1; i <= n; ++i) {
        cin>>a;
        //动态申请空间存放一个节点,临时指针p指向该节点
        p = (struct node *)malloc(sizeof(struct node));
        p->data = a;
        p->next = NULL; //当前节点下一节点为空
        if(head == NULL)
            head = p; //若为第一个创建的,头指针指向该节点
        else
            q->next = p; //上一节点后继指针指向当前节点
        q = p; //指针q指向当前节点
    }
    cin>>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) {
        cout<<t->data<<" ";
        t = t->next; //继续下一节点
    }
    return 0;
}
9
2 3 5 8 9 10 18 26 32
6
2 3 5 6 8 9 10 18 26 32耗时3.5小时终于完成了第四节的学习
第五节 模拟链表
模拟链表不需要指针,却能起到链表的作用,模拟链表还能实现双向链表和循环链表
学习模拟链表可以加深我们对链表的理解,因为它们的思想是一样的,只是工具不同
它使用一个数组存放序列中的数字,使用另一个数组存放下一数字的下标
 
比如上面两个数组,
right[1] == 2表示数组data第1个元素右边元素的下标为2,
right[9] == 0表示数组data第9个元素右边元素不存在
现在需要将6插入5和8中间,怎么做呢?只需要
data[10] = 6; //加在最后
right[3] = 10; //3号右边的元素存放在data[10]
right[10] = 4; //10号元素右边的元素存放在data[4]
 
 
完整代码
#include<iostream>
using namespace std;
int main()
{
    int data[110], right[110];
    int n;
    cin>>n;
    for(int i = 1; i <= n; ++i)
        cin>>data[i]; //读入数据
    for(int i = 1; i <= n; ++i) { //初始化数组right
        if(i != n) right[i] = i + 1;
        else right[i] = 0;
    }
    cin>>data[n + 1]; //待插入数
    //从链表头部开始遍历
    int t = 1;
    while(t != 0) {
        if(data[right[t]] > data[n + 1]) {
            right[n + 1] = right[t]; //right[10] = right[3]
            right[t] = n + 1; //right[3] = 10
            break; //插入完跳出循环
        }
        t = right[t]; //t自增至满足条件或遍历完
    }
    //输出链表所有数
    t = 1; //类似链表中 指针t = head;
    //t = 1少了会从中间开始输出
    while(t != 0) {
        cout<<data[t]<<" ";
        t = right[t];
    }
    return 0;
}
9
2 3 5 8 9 10 18 26 32
6
2 3 5 6 8 9 10 18 26 32代码中 data[n + 1] == 6 ,当满足插入条件时,t == 3, right[n + 1] = 4, right[t] == 10



















