单链表(Singly-Linked List)

简介(Introduction)

  • 链表是一种物理存储单元上非连续、非顺序的存储结构
  • 数据元素的逻辑顺序是通过链表中的指针链接次序实现的
  • 链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成
  • 每个结点包括两个部分:
    1. 存储数据元素的数据域
    2. 存储下一个结点地址的指针域



描述(Description)

  • 结构体加指针类型的链表在开辟内存空间时运行速度很慢
  • 一般利用数组模拟的链表——静态链表



示例(Example)

  • 链表内存图
    image

  • 链表逻辑图示:
    image



代码(Code)

  • 初始化
    int head, e[N], ne[N], idx;
    
    //初始化链表:
    void init() {
    	head = -1;
    	idx = 0;
    }
    

  • 表头插入一个数

    void add_to_head(int x) {
    	e[idx] = x;
    	ne[idx] = head;
    	head = idx++;
    }
    

  • 在第 \(k\) 个数后面插入一个数

    void add(int k, int x) {
    	e[idx] = x;
    	ne[idx] = ne[k];
    	ne[k] = idx++;
    }
    

  • 删除第 \(k\) 个插入的数的后面一个数

    void del(int k) {  // 注意传入时要传 k - 1
    	ne[k] = ne[ne[k]];
    }
    

  • 删除头结点

    head = ne[head];
    

应用(Application)



单链表


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

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

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

注意:题目中第 \(k\) 个插入的数并不是指当前链表的第 \(k\) 个数。例如操作过程中一共插入了 \(n\) 个数,则按照插入的时间顺序,这 \(n\) 个数依次为:第 \(1\) 个插入的数,第 \(2\) 个插入的数,…第 \(n\) 个插入的数。

输入格式

第一行包含整数 \(M\),表示操作次数。

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

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

输出格式

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

数据范围

\(1 \le M \le 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

  • 题解:

    // C++ Version
    
    #include <iostream>
    
    using namespace std;
    
    const int N = 1e6 + 10;
    
    /**
       * head 头节点
       * v    节点值 value
       * ne   下一个节点 next
       * idx  已经使用多少个节点
       */
    int head
    int v[N], ne[N], idx;
    
    //初始化
    void init() {
    	head = -1, idx = 0;
    }
    
    //在链表头插入一个元素
    void add_to_head(int x) {
    	v[idx] = x, ne[idx] = head, head = idx, idx ++ ;
    }
    
    //在 k 后面插入一个数
    void add(int k, int x) {
    	v[idx] = x;
    	ne[idx] = ne[k];
    	ne[k] = idx;
    	idx ++ ;
    }
    
    //删除 k 后面的一个元素
    void del(int k) {
    	ne[k] = ne[ne[k]];
    }
    
    
    int main() {
    	int n;
    	scanf("%d", &n);
    	init();
    	while (n -- ) {
    		char op[2];
    		int a, b;
    		scanf("%s", op);
    		if (op[0] == 'I') {
    			scanf("%d%d", &a, &b);
    			add(a - 1, b);
    		}
    		else if (op[0] == 'H') {
    			scanf("%d", &a);
    			add_to_head(a);
    		}
    		else {
    			scanf("%d", &a);
    			if (!a) head = ne[head];
    			del(a - 1);
    		}
    	}
    
    	for (int i = head; ~i; i = ne[i]) printf("%d ", v[i]);
    
    	return 0;
    }
    

posted @ 2023-05-01 09:16  FFex  阅读(13)  评论(0编辑  收藏  举报