单链表
小王子单链表
问题描述
小王子有一天迷上了排队的游戏,桌子上有标号为 1-10 按顺序摆放的 10 个玩具,现在小王子想将它们按自己的喜好进行摆放。小王子每次从中挑选一个好看的玩具放到所有玩具的最前面。已知他总共挑选了 M 次,每次选取标号为 X 的玩具放到最前面,求摆放完成后的玩具标号。
给出一组输入,M=8 共计排了 8 次,这 8 次的序列为 9,3,2,5,6,8,9,8。 求最终玩具的编号序列。
C++写法
- 定义节点
1 2 3 4
| struct Node{ int data; Node *next; };
|
- 第二步,我们要先构成一个这样的链表:head-> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| Node *head=new Node; void init(){ head->next=nullptr; for(int i=10;i>=1;i--){ Node *temp=new Node; temp->data=i;
temp->next=head->next; head->next=temp; } }
void insert(int x){ Node *temp=new Node; temp->data=x;
temp->next=head->next; head->next=temp; }
void init(){ head->next=nullptr; for(int i=10;i>=1;i--){ insert(i); } }
|
- 第三步,我们要写一个插入函数
1 2 3 4 5 6 7
| void insert(int x){ Node *temp=new Node; temp->data=x;
temp->next=head->next; head->next=temp; }
|
- 第四步,写一个删除函数
1 2 3 4 5 6 7 8 9 10 11 12
| void del(int x){ Node *befor=head; for(Node *T=head->next;T!=nullptr;T=T->next){ if(T->data==x){ Node *temp=T; befor->next=T->next; delete temp; return; } befor=T; } }
|
- 第五步,写一个遍历输出函数,形式接近于删除函数
1 2 3 4 5 6 7
| void show(int i){ cout<<"这是第"<<i<<"次操作"; for(Node *T=head->next;T!=nullptr;T=T->next){ cout<<T->data<<" "; } cout<<endl; }
|
- 主函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| int main(){ init(); show(0); int N; cin>>N; for(int i=1;i<=N;i++){ int x; cin>>x; del(x); insert(x); show(i); } return 0; }
|
Java写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| import java.util.Scanner;
public class Main { static class Node { int data; Node next;
Node(int v) { data = v; } }
static Node head = new Node(1);
static void init() { Node x = head; for (int i = 1; i <= 10; i++) x = (x.next = new Node(i)); x.next = null; }
static void del(int x) {
Node Befor = head; for (Node T = head.next; T != null; T = T.next) { if (T.data == x) { Node temp = T;
Befor.next = T.next;
return; } Befor = T; } }
static void insert(int x) { Node temp = new Node(x);
temp.next = head.next; head.next = temp; }
static void show(int i) {
for (Node T = head.next; T != null; T = T.next) { System.out.print(T.data + " "); } System.out.println(" "); }
public static void main(String[] args) {
int N;
Scanner in = new Scanner(System.in); init(); N = in.nextInt();
for (int i = 0; i < N; i++) { int x = in.nextInt(); del(x); insert(x); show(i); } } }
|
Python 写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| class Node: def __init__(self, value, next=None): self.value = value self.next = next
def createLink(): root = Node(0) tmp = root for i in range(1, 11 ): tmp.next = Node(i) tmp = tmp.next
tmp.next = None return root
def insert(x, linkedroot): tmp = Node(x) tmp.next = root.next root.next = tmp
def delete(x, root): tmp = tmp1 = root
while tmp != None: if tmp.value == x: tmp1.next = tmp.next
tmp1 = tmp tmp = tmp.next
def show(root): tmp = root.next while tmp.next != None: print(tmp.value, end=" ") tmp = tmp.next print("")
if __name__ == '__main__':
n = int(input()) root = createLink()
for i in range(n): x = int(input()) delete(x, root) insert(x, root) show(root)
|
链表的优缺点
优点
插入和删除速度快,保留原有的物理顺序,在插入或者删除一个元素的时候,只需要改变指针指向即可;
没有空间限制, 存储元素无上限, 只与内存空间大小有关;
动态分配内存空间,不用事先开辟内存;
使内存的利用率变高。
缺点
占用额外的空间以存储指针,比较浪费空间,不连续存储,Malloc 函数开辟空间碎片比较多;
查找速度比较慢,因为在查找时,需要循环遍历链表。
时间复杂度
- 查找操作为 O(n), 插入和删除操作为 O(1)。