Contest100000607 - 《算法笔记》7.3小节——数据结构专题(1)->链表处理

文章目录

  • Contest100000607 - 《算法笔记》7.3小节——数据结构专题(1)->链表处理
  • 7.3 链表处理
    • 7.3.1 链表的概念
    • 7.3.2 使用malloc函数或new运算符为链表结点分配内存空间
    • 7.3.3 链表的基本操作
      • 链表的函数代码整理
    • 7.3.4 静态链表
    • PAT例题A1032Sharing
  • Codeup习题
    • 1326-ProblemA-算法2-8~2-11:链表的基本操作
    • 1870-ProblemB-C语言-链表排序
    • 2421-ProblemC-最快合并链表(线性表)
    • 2453-ProblemD-链表查找(线性表)
    • 3596-ProblemE-算法2-24单链表反转
    • 3597-ProblemF-算法2-25有序单链表删除重复元素
  • 链表小结

Contest100000607 - 《算法笔记》7.3小节——数据结构专题(1)->链表处理

7.3 链表处理

7.3.1 链表的概念

线性表分为顺序表和链表;链表由若干结点串联而成,结点在内存中的存储位置通常不连续;结点一般由数据域和指针域构成。

Contest100000607 - 《算法笔记》7.3小节——数据结构专题(1)->链表处理_第1张图片Contest100000607 - 《算法笔记》7.3小节——数据结构专题(1)->链表处理_第2张图片

7.3.2 使用malloc函数或new运算符为链表结点分配内存空间

(1)malloc函数
Contest100000607 - 《算法笔记》7.3小节——数据结构专题(1)->链表处理_第3张图片
接下来的解释终于是我搞懂了malloc语句的含义:
Contest100000607 - 《算法笔记》7.3小节——数据结构专题(1)->链表处理_第4张图片
(2)new运算符
Contest100000607 - 《算法笔记》7.3小节——数据结构专题(1)->链表处理_第5张图片
(3)内存泄漏
Contest100000607 - 《算法笔记》7.3小节——数据结构专题(1)->链表处理_第6张图片Contest100000607 - 《算法笔记》7.3小节——数据结构专题(1)->链表处理_第7张图片

7.3.3 链表的基本操作

###(1)创建链表
在这里插入图片描述
###(2) 查找元素
在这里插入图片描述
###(3)插入元素

Contest100000607 - 《算法笔记》7.3小节——数据结构专题(1)->链表处理_第8张图片Contest100000607 - 《算法笔记》7.3小节——数据结构专题(1)->链表处理_第9张图片
###(4)删除元素

Contest100000607 - 《算法笔记》7.3小节——数据结构专题(1)->链表处理_第10张图片

链表的函数代码整理

//链表的基本操作
#include <cstdio>
#include <cstdlib>
using namespace std;
struct node{//链表结点
	int data;
	node *next; 
};
//创建链表 
node *create(int Array[]){
	node *p,*pre,*head;//pre保存当前结点的前驱结点,head为头结点
	head = new node;//创建头结点
	head->next = NULL;//头结点不需要数据域,指针域初始为NULL
	pre = head;//记录pre为head
	for(int i=0;i<5;i++){
		p = new node;//新建结点
		//将Array[i]赋值给新建的结点作为数据域,也可以scanf输入
		p->data = Array[i];
		p->next = NULL;//新结点的指针域设为NULL
		pre->next = p;//前驱结点的指针域设为当前新建结点的地址
		pre = p;//把pre设为p,作为下个结点的前驱结点 
	} 
	return head;//返回头结点指针 
}
//查找元素
//以head为头结点的链表上计数元素x的个数
int search(node *head,int x){
	int count = 0;//计数器
	node *p = head->next;//从第一个结点开始
	while(p != NULL){//只要没有到链表末尾
		if(p->data == x){
			count++;//当前结点数据域为x,则count++ 
		} 
		p = p->next;//指针移动到下一结点 
	} 
	return count;//返回计数器count 
} 
//插入元素
//将x插入以head为头结点的链表的第pos个位置上
void insert(node *head,int pos,int x){
	node *p = head;
	for(int i = 0;i < pos - 1;i++){
		p = p->next;//pos-1是为了到插入位置的前一个结点 
	}
	node *q = new node;//新建结点
	q->data = x;//新结点的数据域为x
	q->next = p->next;//新结点的下一个结点指向原先插入位置的结点
	p->next = q;//前一个位置的结点指向新结点 
} 
//删除元素
//删除以head为头结点的链表中的所有数据域为x的结点
void del(node *head,int x){
	node *p = head->next;//p从第一个结点开始枚举
	node *pre = head;//pre始终保存p的前驱结点的指针
	while(p != NULL){
		if(p->data == x){//数据域恰好为x,说明要删除该结点
			pre->next = p->next;
			delete(p);
			p = pre->next; 
		}
		else{//数据域不是x,把pre和p都后移一位 
			pre = p;
			p = p->next;
		}
	} 
} 
int main(){
	int Array[5] = {5,3,6,1,2};
	node *L = create(Array);//新建链表,返回的头指针head赋值给L
	L = L->next;//从第一个结点开始有数据域
	while(L != NULL){
		printf("%d",L->data);//输出每个结点的数据域
		L = L->next; 
	} 
	return 0;
}

7.3.4 静态链表

Contest100000607 - 《算法笔记》7.3小节——数据结构专题(1)->链表处理_第11张图片

//7.3.4静态链表
struct Node{
	typename data;//数据域
	int next;//指针域 
}node[size];
	

Contest100000607 - 《算法笔记》7.3小节——数据结构专题(1)->链表处理_第12张图片

PAT例题A1032Sharing

链接:
https://pintia.cn/problem-sets/994805342720868352/problems/994805460652113920
Contest100000607 - 《算法笔记》7.3小节——数据结构专题(1)->链表处理_第13张图片

//PAT例题A1032Sharing
#include <iostream>
#include <cstdio>
#include <cstring>
const int maxn = 100010;
struct NODE{//静态链表 
	char data;//数据域
	int next;//指针域
	bool flag;//结点是否在第一条链表中出现 
}node[maxn];

int main() {
	for(int i=0;i<maxn;i++){
		node[i].flag = false;
	}
	int s1,s2,n;//s1与s2分别代表两条链表的首地址n代表结点数 
	scanf("%d%d%d",&s1,&s2,&n);
	int address,next;//结点地址与后继结点地址
	char data;//数据
	for(int i=0;i<n;i++){//输入结点数据 
		scanf("%d %c %d",&address,&data,&next);
		node[address].data = data;
		node[address].next = next;
	} 
	int p;
	for(p = s1;p != -1;p = node[p].next){
		node[p].flag = true;//枚举第一条链表的所有结点,令其出现次数为1 
	}
	for(p = s2;p != -1;p = node[p].next){
		//找到第一个已经在第一条链表中出现的结点
		if(node[p].flag == true)	break; 
	} 
	if(p != -1){//如果第二条链表还没有到达结尾,说明找到了共用结点
		printf("%05d\n",p); 
	}
	else{
		printf("-1\n");
	}
	return 0;
}	

Codeup习题

Contest100000607 - 《算法笔记》7.3小节——数据结构专题(1)->链表处理
链接: http://codeup.cn/contest.php?cid=100000607
提示:

1、因为输入数据中含有大量的插入和删除操作(不管你信不信,反正我信了),所以必须使用链表,否则很可能会超时。这也是考查链表的特性吧。

2、初始化链表的元素是倒序的,这个使用题目中创建列表的方法(从头部插入)就可以了。

总结:

这题考查的是链表的特性。顺序表中,怎样判断何时使用顺序表何时使用链表呢?就要看它们的特点了。顺序表的特点是随机存取、随机访问,也就是说如果存取和查询比较频繁的话使用顺序表比较合适;链表的特点是插入和删除时不必移动其后的节点,如果插入和删除操作比较频繁的话使用链表比较合适。

1326-ProblemA-算法2-8~2-11:链表的基本操作

链接: http://codeup.cn/problem.php?cid=100000607&pid=0

//1326-ProblemA-算法2-8~2-11:链表的基本操作
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
typedef int Elemtype;
typedef int Status;


typedef struct LNode{
	Elemtype data;
	struct LNode *next;
}LNode,*LinkList;

void GetElem_L(LinkList &L,int i){
	LinkList p;
	p = L->next;
	if(p==NULL)
    {
        printf("get fail\n");
        return;
    }
	int j = 1;
	while(p && j<i){
		p = p->next;
		++j;
	}
	if(!p || j>i){
		printf("get fail\n");
		return;
	}
	cout<<p->data<<endl;
//	e = p->data;
	return;
}
void ListInsert_L(LinkList &L,int i,Elemtype e){
	LinkList p,s;
	p = L;
	int j = 0;
	/*该插入方法无法判断差错出错和初始为空的插入之间的区别 
	while(p && j> i - 1){
		p = p->next;
		++j;
	}
	if(!p || j > i-1){
		printf("insert fail\n");
        return;
	}
	*/
	for(int j=0;j<i-1;j++){
    	p = p->next;
    	if(p == NULL){
    		printf("insert fail\n");
        	return;
		}
	}
	
	//	return ERROR;
		s = (LinkList)malloc(sizeof(LNode));
		s->data = e;
		s->next = p->next;
		p->next = s;
		printf("insert OK\n");
		return;
}
void ListDelete_L(LinkList &L,int i){
//	LNode *p,*pre;
//	p = L->next;
	LNode *p = L->next;;
	LNode *pre = L;
	if(p == NULL){
		printf("delete fail\n");
        return;
	} 
	for(int j=0;j<i-1;j++){
		pre = p;
		p = pre->next;
	}
	if(p ==NULL){
		printf("delete fail\n");
        return;
	}
	pre->next = p->next;
	free(p);
	printf("delete OK\n");
	return;
}
void CreateList_L(LinkList &L,int n){
	LinkList p;
	int i;
	L = (LinkList)malloc(sizeof(LNode));
	L->next = NULL;
	for(i=n;i > 0;i--){
		p = (LinkList)malloc(sizeof(LNode));
		scanf("%d",&p->data);
		p->next = L->next;
		L->next = p;
	}
}
void ListShow(LinkList &L){
	LinkList p = L->next;
	if(p == NULL){
		printf("Link list is empty\n");
		return;
	}
	while(p->next){
		cout<<p->data<<" ";
		p = p->next;
	}
	cout<<p->data<<endl;
}

int main(){
	LinkList L;
	int n;
	cin>>n;//初始化链表n个元素 
	CreateList_L(L,n);
	int op_num;
	cin>>op_num;
	while(op_num--){
//		int del_number,get_number;
		string str;
		cin>>str;
		if(str == "show"){
			ListShow(L);
		}
		else if(str=="delete"){
			int index;cin>>index;
			ListDelete_L(L,index);
		}
		
		else if(str=="insert"){
			int index,number;
			cin>>index>>number;
			ListInsert_L(L,index,number);
		}
		else if(str == "get"){
			int index;cin>>index;
			GetElem_L(L,index);
		}	
	}
	return 0;
}
	

1870-ProblemB-C语言-链表排序

链接: http://codeup.cn/problem.php?cid=100000607&pid=1

//1870-ProblemB-C语言-链表排序
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;

struct student{
	int no;//学号
	int grade;//成绩 
}stu[100010];
bool cmp(student x,student y){//结构体排序规则 
	return x.no < y.no;
}

int main(){
	int N,M;
	while(cin>>N>>M){
		for(int i=0;i<N+M;i++){
			cin>>stu[i].no>>stu[i].grade;
		}
		sort(stu,stu+N+M,cmp);
		for(int i=0;i<N+M;i++){
			cout<<stu[i].no<<" "<<stu[i].grade<<endl;
		}
	}
	return 0;
}
	

2421-ProblemC-最快合并链表(线性表)

链接: http://codeup.cn/problem.php?cid=100000607&pid=2

//2421-ProblemC-最快合并链表(线性表)
#include<iostream>
using namespace std;
//按先后顺序输出即可
int main() {
	int n, m,num[100010];
	/*
	while (cin >> n) {
		while (n--) {
			cin >> x;
			cout << x << " ";
		}
		cin >> m;
		while (m--) {
			cin >> x;
			cout << x << " ";
		}
		*/
	while(cin>>n){
		for(int i=0;i<n;i++){
			cin>>num[i];
		}
		int m;cin>>m;
		int sum = m+n;
		for(int i=n;i<sum;i++){
			cin>>num[i];
		}
//		int sum = m+n;
		int index;
		for(index=0;index<sum-1;index++){
			cout<<num[index]<<" ";
		}
		cout<<num[index]<<endl;
		
		cout << endl;
	}
	return 0;
}
	

2453-ProblemD-链表查找(线性表)

链接: http://codeup.cn/problem.php?cid=100000607&pid=3

//	2453-ProblemD-链表查找(线性表)
//非链表实现
#include<iostream>
using namespace std;

int main() {
	int a[100010];
	int x,n;
	bool exisit = 0;
	int index = 0;
	while(cin>>x>>n){
		for(int i=0;i<n;i++){
			cin>>a[i];
			if(x == a[i]){
				exisit = i;
			}
			if(x>a[i-1] && x<a[i]){
				index = i;
			}
		}
		if(exisit){
			
			int temp = a[exisit];
			a[exisit] = a[exisit+1];
			a[exisit+1] = temp;
			for(int i=0;i<n-1;i++){
				cout<<a[i]<<" ";
			}
			cout<<a[n-1]<<endl;
		}
		else{
			cout<<"no"<<endl;
			for(int i=n-1;i>=index;i--){
				a[i+1]=a[i];
			}
			a[index] = x;
			for(int i=0;i<n;i++){
				cout<<a[i]<<" ";
			}
			cout<<a[n]<<endl;
		}
	}
	return 0;
}
	

3596-ProblemE-算法2-24单链表反转

链接: http://codeup.cn/problem.php?cid=100000607&pid=4

//3596-ProblemE-算法2-24单链表反转
#include <iostream>
#include <algorithm>
using namespace std;

int main() {
	int n;int a[100010];int cnt=0;
	while(cin>>n){
		if(!n){
			cout<<"list is empty"<<endl;
			break;	
		}
		for(int i=0;i<n;i++){
			cin>>a[i];
		}
		for(int i=0;i<n-1;i++){
			cout<<a[i]<<" ";
		}
		cout<<a[n-1]<<endl;
		reverse(a,a+n);
		for(cnt=0;cnt<n-1;cnt++){
			cout<<a[cnt]<<" ";
		}
		cout<<a[cnt]<<endl;
	}
	
	return 0;
}
	

3597-ProblemF-算法2-25有序单链表删除重复元素

链接: http://codeup.cn/problem.php?cid=100000607&pid=5

//3597-ProblemF-算法2-25有序单链表删除重复元素
#include <iostream>
#include <algorithm>
using namespace std;

int main() {
	int n;
	int a[100010];
	while(cin>>n){
		int cnt = 0;
		if(!n){
			cout<<"list is empty"<<endl;
			break;	
		}
		for(int i=0;i<n;i++){
			cin>>a[i];
		}
		//输出原序列 
		for(int i=0;i<n-1;i++){
			cout<<a[i]<<" ";
		}
		cout<<a[n-1]<<endl;
		//去除重复元素 
		for(int i=0;i<n;i++){//注意此处i从0到n-1,即使n-1+1=n没有输入数,因为需要将处理a[n-1] 
			if(a[i] != a[i+1]){//巧妙覆盖法 
				a[cnt++] = a[i];
			}
		}
		//输出处理后的序列 
		for(int i=0;i<cnt-1;i++){//此处cnt++,所以a中最后一个数为a[cnt-1] 
			cout<<a[i]<<" ";
		}
		cout<<a[cnt-1]<<endl;
		
	/*
	5 1 2 3 4 5
	5 1 1 2 2 3
	0
	*/	
		
	}
	return 0;
}
	

链表小结

线性表分为顺序表和链表;链表由若干结点串联而成,结点在内存中的存储位置通常不连续;结点一般由数据域和指针域构成。使用malloc函数或new运算符为链表结点分配内存空间,对应free()和delete()来释放内存;常用参数为创建链表、查找元素、插入元素、删除元素,具体可参考我的数据结构代码https://blog.csdn.net/qq_34767784/category_9061413.html

你可能感兴趣的:(算法笔记刷题笔记,算法笔记,数据结构,链表)