目录
题目描述
小王子有一天迷上了排队的游戏,桌子上有标号为 1-101−10 的 1010 个玩具,现在小王子将他们排成一列,可小王子还是太小了,他不确定他到底想把那个玩具摆在哪里,直到最后才能排成一条直线,求玩具的编号。已知他排了 MM 次,每次都是选取标号为 XX 个放到最前面,求每次排完后玩具的编号序列。
要求一:采用循环链表解决
输入描述
第一行是一个整数 MM,表示小王子排玩具的次数。
随后 MM 行每行包含一个整数 XX,表示小王子要把编号为 XX 的玩具放在最前面。
输出描述
共 MM 行,第 ii 行输出小王子第 ii 次排完序后玩具的编号序列。
输入输出样例
输入
5
3
2
3
4
2
输出
3 1 2 4 5 6 7 8 9 10
2 3 1 4 5 6 7 8 9 10
3 2 1 4 5 6 7 8 9 10
4 3 2 1 5 6 7 8 9 10
2 4 3 1 5 6 7 8 9 10
思路
题目大意就是,给一个排好顺序的数组,输入一个数让这个数提到最前面。可以用数组实现也可以用链表实现,用数组实现要进行多次交换,本文用链表实现。
解决: 用双向链表实现
-
构建双向链表
void ini() { Node *p = head; //遍历操作 for (int i = 0; i < 10; i++) {//每次创建一个结点,让它pre指向上一个结点,pre指向它本身 Node *newNode = new Node(i); newNode->pre = p; p->next = newNode; p = p->next;//让p往后走 } }
-
插入(从头节点)
插入newNode/temp:由原本的head→head.next
变成head→temp→原head.next
就是说要让temp指向head.next,head指向temp(顺序反过来会导致temp找不到一开始head的next是谁)
但因为是双链表,还得构建两个前缀节点,如果head.next是空指针就不需要。
即:head←head.next
变成head←temp←原head.next(非空的时候)
构建2次next,2次pre
void insert(int x) { //插入到head后面 创建新节点,赋值x Node *newNode = new Node(x); 改变两个next newNode->next = head->next; head->next = newNode; 改变两个prev newNode->pre = head; if (newNode->next)//存在才往回指 newNode->next->pre = newNode; }
-
删除
因为插入在头部一个数,本身这个数还在,需要删掉,同时不改变链表整体结构
p1→target→target.next p1←target←target.next
变成:p1→target.next p1←target.next
void Del(int x) {//x为目标值
Node *p = head;
while (p) { //双向链表不需要定位上一个结点
if (p->val==x) {
p->pre->next = p->next;
p->next->pre = p->pre;
return;
}
p = p->next;
}
}