一、概述
- 含义:链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构。它可以根据需要开辟内存单元。链表有一个“头指针”变量,以head表示,它存放一个地址。该地址指向一个元素。链表中每一个元素称为“结点”,每个结点都应包括两个部分:一为用户需要用的实际数据,二为下一个结点的地址。因此,head指向第一个元素:第一个元素又指向第二个元素;……,直到最后一个元素,该元素不再指向其它元素,它称为“表尾”,它的地址部分放一个“NULL”(表示“空地址”),链表到此结束。
- 特点:
①长度不固定,可以任意增删。
②存储空间不连续,数据元素之间使用指针相连,每个数据元素只能访问周围的一个元素(根据单链表还是双链表有所不同)。
③存储密度小,因为每个数据元素,都需要额外存储一个指向下一元素的指针(双链表则需要两个指针)。
④要访问特定元素,只能从链表头开始,遍历到该元素,时间复杂度为 O(n)。
⑤在特定的数据元素之后插入或删除元素,不涉及到其他元素的移动,因此时间复杂度为 O(1)。双链表还允许在特定的数据元素之前插入或删除元素。 - 与顺序表(数组)的比较 :便于插入或删除元素,但无法直接访问元素。
- 分类:单链表,双链表。
- 操作:创建,遍历,插入,删除。
- 习惯:
- head:头结点 tail:尾结点 temp:当前结点 follow: 当前结点前一结点 unit:插入结点 pointer:遍历指针
- create() 创建 insert()插入 del()删除
二、实现
- 单链表
- 创建 遍历
/* ======================================= 单向链表:打印1~n的数字 创建 遍历 ======================================= */ #include<iostream> using namespace std; struct student{ //定义结构体 数据+指针 int grade; student *next; }; student *create(int N) //创建单向链表 { student *temp,*head; int num=1,n=1; head=new student; //头节点 temp=head; while(n<=N){ temp->grade=num; temp->next=new student; //新建下一节点 temp=temp->next; //指向下一节点 num++; n++; } temp->next=NULL; return head; //返回head指针 } int main() { int n; cin >> n; student *pointer=create(n); //创建pointer指针,指向head while(pointer->next!=NULL){ //遍历,为空指针时结束 cout << pointer->grade << ' '; pointer=pointer->next; } return 0; }
- 插入
/* ======================================= 单向链表:打印1~n的数字 插入 i在 i的前面 ======================================= */ #include<iostream> using namespace std; struct student{ int grade; student *next; }; student *create(int N) { student *temp,*head; int num=1,n=1; head=new student; temp=head; while(n<=N){ temp->grade=num; temp->next=new student; temp=temp->next; num++; n++; } temp->next=NULL; return head; } student *insert(student *head,int N) { student *temp,*unit,*follow; temp=head; unit=new student; unit->grade=N; unit->next=NULL; while( temp!=NULL && temp->grade<N ){ follow=temp; temp=temp->next; } //cout << follow->grade << ' '<<temp->grade <<endl <<follow->next <<' ' << temp->next << endl; // 测试数据 5 4/5/6/7 if(temp->grade>N) return head; if(temp==head){ unit->next=head; head=unit; } else{ follow->next=unit; unit->next=temp; } return head; } int main() { int n,i; cin >> n >> i ; student *pointer=create(n); pointer=insert(pointer,i); while(pointer->next!=NULL){ cout << pointer->grade << ' '; pointer=pointer->next; } return 0; }
- 删除
/* ======================================= 单向链表:打印1~n的数字 删除 数字i ======================================= */ #include<iostream> using namespace std; struct student{ int grade; student *next; }; student *create(int N) { student *temp,*head; int num=1,n=1; head=new student; temp=head; while(n<=N){ temp->grade=num; temp->next=new student; temp=temp->next; num++; n++; } temp->next=NULL; return head; } student *del(student *head,int N) { student *temp,*follow,*unit; temp=head; if(head==NULL){ return head; } if(head->grade==N){ head=head->next; delete temp; return head; } while(temp!=NULL&&temp->grade!=N){ follow=temp;temp=temp->next; } if(temp!=NULL){ follow->next=temp->next; //不能是,follow=temp delete temp; } return head; } int main() { int n,i; cin >> n >> i ; student *pointer=create(n); pointer=del(pointer,i); while(pointer->next!=NULL){ cout << pointer->grade << ' '; pointer=pointer->next; } return 0; }
- 创建 遍历
- 双链表
三、应用
6378:删除数组中的元素(链表)
-
总时间限制:
- 1000ms 内存限制:
- 65536kB
-
描述
-
给定N个整数,将这些整数中与M相等的删除
假定给出的整数序列为:1,3,3,0,-3,5,6,8,3,10,22,-1,3,5,11,20,100,3,9,3
应该将其放在一个链表中,链表长度为20
要删除的数是3,删除以后,链表中只剩14个元素:1 0 -3 5 6 8 10 22 -1 5 11 20 100 9要求:必须使用链表,不允许使用数组,也不允许不删除元素直接输出
程序中必须有链表的相关操作:建立链表,删除元素,输出删除后链表中元素,释放链表
不符合要求的程序即使通过,也会算作0分
输入
-
输入包含3行:
第一行是一个整数n(1 <= n <= 200000),代表数组中元素的个数。
第二行包含n个整数,代表数组中的n个元素。每个整数之间用空格分隔;每个整数的取值在32位有符号整数范围以内。
第三行是一个整数k,代表待删除元素的值(k的取值也在32位有符号整数范围内)。
输出
-
输出只有1行:
将数组内所有待删除元素删除以后,输出数组内的剩余元素的值,每个整数之间用空格分隔。
样例输入
-
20 1 3 3 0 -3 5 6 8 3 10 22 -1 3 5 11 20 100 3 9 3 3
样例输出
-
1 0 -3 5 6 8 10 22 -1 5 11 20 100 9
#include<iostream> using namespace std; struct list{ int num; list *next; }; list *create(int n) { int k,x=1; list *head,*temp; head=new list; temp=head; while(x<=n){ cin >> k; temp->num=k; temp->next=new list; temp=temp->next; x++; } temp->next=NULL; return head; } list *del(list *head,int k) { list *temp,*follow; temp=head; if(head==NULL) { return head; } while(head->num==k){ head=head->next; temp=head; } while(temp->next!=NULL){ if(temp->num!=k) { follow=temp; temp=temp->next; } else { follow->next=temp->next; temp=follow->next; } } return head; } int main() { int n,k; cin >> n; list *pointer=create(n); cin >> k; pointer=del(pointer,k); while(pointer->next!=NULL){ cout << pointer->num << ' ' ; pointer=pointer->next; } return 0; }