链表板子(指针版,数组版,STL版)

指针版:

用到malloc动态开组,平时做项目可以用,打比赛算了

#include <stdio.h>
#include <stdlib.h>
#include<iostream>
using namespace std;
struct list{
    int num;
    struct list *next;
};

struct list* p;
struct list* pm;//head

typedef struct list list_single;  
list *creat_list_tail(int n){
    //尾插法创建一个链表,并返回一个头指针
    int i=0;
    list *head,*rear,*node;
    head=(list *)malloc(sizeof(list));
    rear=head;
    for(;i<n;i++){
        node=(list *)malloc(sizeof(list));
        node->num=i+1;//这里值需要变通
        rear->next=node;
        rear=node;
    }
    rear->next=NULL;
    head->num=n;
    return head;
}
void list_delete_val(list_single *list,int val){
    list_single *pre,*temp;
    while(list!=NULL){
        pre=list;//记录现在的节点,链表头指针没使用数据域,因此可以从头指针后一个节点开始查询
        temp=list->next;//查询的事当前节点指向下一个节点的值
        if(temp==NULL){
            printf("没找到相关节点val=%d\n",val);
            return;
        }
        if(temp->num==val){
            pre->next=temp->next;
            free(temp);   //删除后记得释放内存!
            return;
        }
        list=list->next;    
    }
}
void list_insert(list_single *list,int i,int x){
    list_single *target = (list_single *)malloc(sizeof(list_single));
    list_single *pre;
    int num=0;
    target->num=x;
    if(i<0){
        printf("位置输入错误\n");
        return ;
    }
    while(list!=NULL){
        //在最后一个位置和第一个位置特殊处理
        if(list->next==NULL) {
            printf("这是最后一个位置\n");
            list->next=target;
            target->next=NULL;
            return;
        }
        else if(i==0){
            pre=list->next;
            printf("这是第一个位置\n");
            list->next=target;
            target->next=pre;
            return;
        }
        if(num==i){    
            pre=list->next;
            list->next=target;
            target->next=pre;
            break;
        }
        num++;
        list=list->next;
    }
}
int main(){
    int n;
    cout<<"输入链表长度:";
    cin>>n;
    
    p =creat_list_tail(n);
    pm=p;
    while (pm->next != NULL){
        printf("%-5d", pm->next->num);
        pm = pm->next;
    }
    printf("\n");
    
    printf("在第0位插入424:\n");
    list_insert(p,0,424);
    pm=p;
    while (pm->next != NULL){
        printf("%-5d", pm->next->num);
        pm = pm->next;
    }
    printf("\n");
    
    printf("删除为5的数字:\n");
    list_delete_val(p,5);
    pm=p;
    while (pm->next != NULL){
        printf("%-5d", pm->next->num);
        pm = pm->next;
    }
    printf("\n");
}

普通版,用结构体+node一维数组

这个版本带了左右插入与删除,但我觉得可以直接用

原题是洛谷P1160:

队列安排 - 洛谷

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
struct node{
    int L, R;
}a[100003];
int n, m;
inline void addRight(int x, int pos) { //插入右边
    a[x].L = pos;
    a[a[pos].R].L = x;
    a[x].R = a[pos].R;
    a[pos].R = x;
}
inline void addLeft(int x, int pos) { //插入左边
    a[x].R = pos;
    a[a[pos].L].R = x;
    a[x].L = a[pos].L;
    a[pos].L = x;
}
inline void del(int x) {
    if(a[x].L == -1) return;
    a[a[x].L].R = a[x].R;
    a[a[x].R].L = a[x].L;
    a[x].L = -1;
    a[x].R = -1;
}
inline void go() {
    int x = a[0].R;
    while(1) {
        cout<<x<<" ";
        if(a[x].R == -1) break;
        x = a[x].R;
    }
}
inline void init() {
    for(int i = 1; i <= n; ++i) a[i].L = a[i].R = -1;
    a[1].R = -1; a[1].L = 0; a[0].R = 1;
}
int main() {
    scanf("%d", &n);
    int cmd1, cmd2;
    init();
    for(int i = 2; i <= n; ++i) {
        scanf("%d %d", &cmd1, &cmd2);
        if(!cmd2) addLeft(i, cmd1);
        else addRight(i, cmd1);
    }
    scanf("%d", &m);
    for(int i = 1; i <= m; ++i) {
        scanf("%d", &cmd1);
        del(cmd1);
    }
    go();
    return 0;
}

这里一个有意思的点,说到删除有的时候没必要真的删除,设为隐藏什么之类的可以减少操作。

STL版:题解 P1160 【队列安排】 - Orina_zju 的博客 - 洛谷博客

list<int> myList;
myList.push_front(1);
myList.push_back(2);
//对应地,pop_front()用于移除头部的元素,pop_back()用于移除尾部的元素。

typedef list<int>::iterator Iter;
Iter itBegin = myList.begin();
Iter itEnd = myList.end();
for (; itBegin != itEnd; ++itBegin)
    printf(" %d", *itBegin);

这段的下半部分代码演示的是list提供的,用于访问内部元素的迭代器。迭代器的类型是list<Tp>::iterator(这里模板参数Tp需要与你操作的链表一致)。迭代器的用法和指针有些像,可以用*运算符访问内部的元素,++和--运算符可以将它后移或前移一位(建议写成前置形式),
用==和!=运算符进判断两个迭代器所指的位置是否一致。但要注意:list的迭代器不支持it += x或it1 - it2这样的运算,也不支持<,<=等运算符。

begin()成员函数返回指向头部元素的迭代器。end()成员函数返回指向末尾位置的迭代器。这个“末尾位置”指的是最后一个元素再往后一位,也就是说end()所指的位置不包含有效元素,它相当于一个虚设的节点。这样设计是为了满足C++标准库表示区间时左闭右开的惯例。

insert(it, val)成员函数用于在链表中插入元素。it为该链表的一个迭代器,val为待插入的值,插入后val位于it所指位置的前一位。返回值为一个迭代器,表示val插入到了哪个位置。remove(it)成员函数用于删除某个迭代器所指的节点。注意在删除之后it就失效了,除非给it重新赋值,否则对它的任何操作都会导致错误!remove(val)用于移除所有值为val的节点

#include <cstdio>
#include <list>
using namespace std;
using Iter = list<int>::iterator;//自定义了哈 

const int maxN = 1e5 + 10;
Iter pos[maxN];
list<int> queList;
bool erased[maxN];//这里懒得删除了,直接标记了 
int N;

void buildQueue(){
	queList.push_front(1);
	pos[1] = queList.begin();
	for (int i = 2; i <= N; i++){
		int k, p;
    	scanf("%d%d", &k, &p);
    	if (p == 0)pos[i] = queList.insert(pos[k], i); //left
    	else{
     	    auto nextIter = next(pos[k]);
       		pos[i] = queList.insert(nextIter, i); //right
    	}
    }
    int M;
    scanf("%d", &M);
    for (int x, i = 1; i <= M; i++){
    	scanf("%d", &x);
        if (!erased[x])queList.erase(pos[x]);
        erased[x] = true;
    }
}

int main(){
    scanf("%d", &N);
    buildQueue();
    bool first = true;
    for (int x:queList){
        if (!first)putchar(' ');
        first=false;
      printf("%d",x);
    }
    putchar('\n');
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值