文章目录
- 一、前言
- 二、有序单链表去重
-
- 2.1 去重后的链表放在原链中
- 2.2 去重后的链表放在新链中
- 三、单链表无序去重data绝对值
- 四、单链表删去data为x的结点
- 五、单链表按data值排序
-
- 5.1 按data递增排序
- 5.2 按data递减排序
- 六、单链表拆分
-
- 6.1 两个头插
- 6.2 两个尾插
- 6.3 原链尾插,新链头插
- 6.4 原链头插,新链尾插
- 七、单链表合并
-
- 7.1 两个子链表尾插
- 7.2 两个子链表头插
- 7.3 第一条链头插 第二条链尾插
- 7.4 第一条链尾插 第二条链头插
- 八、小结
一、前言
数据结构中单链表有序去重是单链表最基本的操作之一,将一个有序单链表中的重复节点删去。
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
typedef struct node{
int data;
struct node *next;
}Node,*Linklist;
//去重 一定是原链 去重一定是要破坏原链的,如果一定不破坏原链 就将原链所有元素复制到新链
//递增有序去重 输入 7 10 10 21 30 42 42 42 51 70
//递减有序去重 输入 70 51 42 42 42 30 21 10 10 7
void deleteSame(Linklist str1){
Linklist p=str1->next;
if(p==NULL){
return;
}
while(p->next!=NULL){
Linklist u=p->next;
if(p->data==u->data){
p->next=u->next;
free(u);//free(u) 删除一个结点 free(str2)删除一个链表
}
else
p=p->next;
}
}
int main()
{
int n;
cin>>n;
int a[100];
for(int i=0;i<n;i++)
cin>>a[i];
Linklist first=new Node;
Linklist r=first;
for(int i=0;i<n;i++){
Linklist s=new Node;
s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
Linklist p=first->next;//重置p
while(p){
cout<<p->data;
cout<<" ";
p=p->next;
}
cout<<endl;
deleteSame(first);
p=first->next;//重置P
while(p){
cout<<p->data;
cout<<" ";
p=p->next;
}
cout<<endl;
return 0;
}
运行结果:
10 输入
7 10 10 21 30 42 42 42 51 70 输入
7 10 10 21 30 42 42 42 51 70 中间打印
7 10 21 30 42 51 70 输出
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
typedef struct node{
int data;
struct node *next;
}Node,*Linklist;
//新链条一定是新节点
Linklist deleteSame3(Linklist str1){
//复制 good
Linklist pa=str1->next;
Linklist str3=new Node;//尾插法
Linklist r=str3;
//将str1所有元素复制给str3 good
while(pa){
Linklist s=new Node;
s->data=pa->data;
r->next=s;
r=s;
pa=pa->next;//复制元素
}
r->next=NULL;
pa=str3->next;
if(pa==NULL)
return NULL;
while(pa->next!=NULL){//因为之前的判断 p已经不为空了
Linklist u=pa->next;
if(pa->data==u->data){
pa->next=u->next;
free(u);
}else {
pa=pa->next;
}
}
return str3;
}
int main()
{
int n;
cin>>n;
int a[100];
for(int i=0;i<n;i++)
cin>>a[i];
Linklist first=new Node;
Linklist r=first;
for(int i=0;i<n;i++){
Linklist s=new Node;
s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
Linklist p=first->next;//重置p
while(p){
cout<<p->data;
cout<<" ";
p=p->next;
}
cout<<endl;
Linklist result=deleteSame3(first);
p=result->next;
while(p){
cout<<p->data;
cout<<" ";
p=p->next;
}
return 0;
}
10 输入
7 10 10 21 30 42 42 42 51 70 输入
7 10 10 21 30 42 42 42 51 70 中间打印
7 10 21 30 42 51 70 输出
有序单链表去重因为有序,数值重复元素处于相邻位置,故只需要遍历一次,时间复杂度为O(n);
无序单链表中,去掉data绝对值相同的结点,处理后输出单链表
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
typedef struct node {
int data;
struct node *next;
}Node,*Linklist;
void myfunction(Linklist str1,int n){//n是单链表元素绝对值最大的
Linklist pre=str1;//要删除这个节点 必须保留一个前驱节点
Linklist p=str1->next;
Linklist u;
int m;//n是绝对值中最大的 m是某个数字的绝对值
int* q=(int *)malloc(sizeof(int)*(n+1));//动态数组 这个不能错 并且初始化
for (int i=0;i<n+1;i++)
q[i]=0;
while(p){
m=p->data>0?p->data:-p->data;//取绝对值
cout<<"处理前:";
cout<<m<<endl;
if(q[m]==0){
q[m]=1;
pre=pre->next;
p=p->next;
cout<<"处理后:";
cout<<m<<endl;
}else {
//删除p
u=pre->next;
pre->next=p->next;
p=p->next;//移动一次 因为p所指向的节点没了 而且p是操作对象
free(u);
}
}
free(q);
}
int main() // 1 - 2 2 4 -3
{
int a[5];
for (int i=0;i<5;i++){
cin>>a[i];
}
Linklist first=new Node;
Linklist r=first;
for (int i=0;i<5;i++){
Linklist s=new Node;
s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
Linklist p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
//先变为绝对值 取出绝对值中最大的
for (int i=0;i<5;i++){
a[i]=a[i]>0?a[i]:-a[i];
}
int maxVal=a[0];
for (int i=0;i<5;i++){
if(a[i]>maxVal)
maxVal=a[i];
}
cout<<maxVal<<endl;
myfunction(first,maxVal);
p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
return 0;
}

四、单链表删去data为x的结点
代码:
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
typedef struct node{
int data;
struct node *next;
}Node,*Linklist;
void deletex(Linklist str1,int x){
Linklist pre=str1;
Linklist p=pre->next;
while(p){
if(p->data==x){
Linklist u=p;
pre->next=p->next;
p=p->next;
free(p);
}else {
pre=p;
p=p->next;
}
}
}
int main()
{
int a[5];
for (int i=0;i<5;i++)
cin>>a[i];
Linklist first=new Node;
Linklist r=first;
for (int i=0;i<5;i++){
Linklist s=new Node;
s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
Linklist p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
while(true){
int n;
cin>>n;
deletex(first,n);
p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
}
return 0;
}
#include<stdio.h>
#include<stdlib.h>
using namespace std;
typedef struct node{
int data;
struct node *next;
}Node,*Linklist;
void mysort(Linklist str1){
Linklist pre=str1,p=pre->next;
Linklist r=p->next;
p->next=NULL;
p=r;
while(p){
r=p->next;
pre=str1;
while(pre->next!=NULL&&pre->next->data<p->data){//这里一定是pre后面的那个的data 而不是pre的data
pre=pre->next;
}
p->next=pre->next;
pre->next=p;
p=r;
}
}
int main()
{
int a[5];
for (int i=0;i<5;i++)
cin>>a[i];
Linklist first=new Node;
Linklist r=first;
for (int i=0;i<5;i++){
Linklist s=new Node;
s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
Linklist p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
mysort(first);
p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
return 0;
}
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
typedef struct node{
int data;
struct node *next;
}Node,*Linklist;
//递减顺序
void mysort2(Linklist str1){
Linklist pre=str1,p=pre->next;
Linklist r=p->next;
p->next=NULL;
p=r;
while(p){
r=p->next;
pre=str1;
while(pre->next!=NULL&&pre->next->data>
p->data)
pre=pre->next;
p->next=pre->next;
pre->next=p;
p=r;
}
}
int main()
{
int a[5];
for (int i=0;i<5;i++)
cin>>a[i];
Linklist first=new Node;
Linklist r=first;
for (int i=0;i<5;i++){
Linklist s=new Node;
s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
Linklist p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
mysort2(first);
p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
return 0;
}
数据结构中单链表的拆分是单链表最基本的操作之一,将一个单链表拆分为两个,得到的两个子链表可以为正序(尾插)可以为逆序(头插),一个子链表可以用原来的链表内存空间,另一个子链表则需要开辟新的内存空间。
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
typedef struct node{
int data;
struct node *next;
}Node,*Linklist;
//12345678910拆分为 97531 108642 两个头插 first result 拆分一个while 循环里面有两步
Linklist function1(Linklist str1){
//根据仅仅对目标操作的原则 拆分的目标是str1 str2 头插法 两个部分 尾插法 三个部分
Linklist p=str1->next;
str1->next=NULL;
Linklist str2=new Node;
str2->next=NULL;
while(p){
Linklist u=p->next;
p->next=str1->next;
str1->next=p;
p=u;
u=p->next;
p->next=str2->next;
str2->next=p;
p=u;
}
return str2;
}
int main()
{
int a[10];
for (int i=0;i<10;i++)
cin>>a[i];
Linklist first=new Node;
Linklist r=first;
for(int i=0;i<10;i++){
Linklist s=new Node; s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
Linklist p=first->next;
//初始化和打印的时候 先Null 在p 没有关系 因为这个时候 first->next 经过初始化已经改变了
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
Linklist result=function1(first);
p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
p=result->next;
while(p){
cout<<p->data;
p=p->next;
}
return 0;
}
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
typedef struct node{
int data;
struct node *next;
}Node,*Linklist;
//12345678910拆分为 13579 246810 两个尾插 first result
Linklist function2(Linklist str1){
//拆分两个目标 str1 str2 合并一个目标 str1 尾插三个部分 头插两个部分
//拆分一个源 一个工作指针p 合并两个源 两个工作指针pa pb
Linklist ra=str1;
Linklist str2=new Node;
Linklist rb=str2;
Linklist p=str1->next;
while(p){
ra->next=p;
ra=p;
p=p->next;
rb->next=p;
rb=p;
p=p->next;
}
ra->next=NULL;
rb->next=NULL;
return str2;
}
int main()
{
int a[10];
for (int i=0;i<10;i++)
cin>>a[i];
Linklist first=new Node;
Linklist r=first;
for(int i=0;i<10;i++){
Linklist s=new Node; s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
Linklist p=first->next;
//初始化和打印的时候 先Null 在p 没有关系 因为这个时候 first->next 经过初始化已经改变了
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
Linklist result=function2(first);
p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
p=result->next;
while(p){
cout<<p->data;
p=p->next;
}
return 0;
}
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
typedef struct node{
int data;
struct node *next;
}Node,*Linklist;
//12345678910 变为 13579 108642 原链尾插 新链头插
Linklist function3(Linklist str1){
Linklist ra=str1;
Linklist str2=new Node;
str2->next=NULL;
Linklist p=str1->next;
while(p){
ra->next=p;
ra=p;
p=p->next;
Linklist u=p->next;
p->next=str2->next;
str2->next=p;
p=u;
}
ra->next=NULL;
return str2;
}
int main()
{
int a[10];
for (int i=0;i<10;i++)
cin>>a[i];
Linklist first=new Node;
Linklist r=first;
for(int i=0;i<10;i++){
Linklist s=new Node; s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
Linklist p=first->next;
//初始化和打印的时候 先Null 在p 没有关系 因为这个时候 first->next 经过初始化已经改变了
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
Linklist result=function3(first);
p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
p=result->next;
while(p){
cout<<p->data;
p=p->next;
}
return 0;
}
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
typedef struct node{
int data;
struct node *next;
}Node,*Linklist;
//12345678910 拆分为 97531 246810 原链头插 新链尾插
Linklist function4(Linklist str1){
Linklist p=str1->next;
str1->next=NULL;
Linklist str2=new Node;
Linklist r=str2;
while(p){
Linklist u=p->next;
p->next=str1->next;
str1->next=p;
p=u;
r->next=p;
r=p;
p=p->next;
}
r->next=NULL;
return str2;
}
int main()
{
int a[10];
for (int i=0;i<10;i++)
cin>>a[i];
Linklist first=new Node;
Linklist r=first;
for(int i=0;i<10;i++){
Linklist s=new Node; s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
Linklist p=first->next;//初始化和打印的时候 先Null 在p 没有关系 因为这个时候 first->next 经过初始化已经改变了
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
Linklist result=function4(first);
p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
p=result->next;
while(p){
cout<<p->data;
p=p->next;
}
return 0;
}
小结:
单链表拆分需要充分考虑到子链表的顺序和原链表顺序的关系,顺序相同,子链表尾插,顺序相反,子链表头插;
因为每次循环要插入两个子链表中各一个元素,所以每次循环工作指针移动两次;
数据结构中单链表的合并是单链表最基本的操作之一,将两个子链表合并为一个,得到的总链表默认使用第一个子链表的空间。
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
typedef struct node{
int data;
struct node *next;
}Node,*Linklist;
// 13579 246810 合并为 1235678910 两个尾插 拆分为两个 所以一个while循环中有两步 合并为一个 所以一个while循环中只有一步
//但是因为是有序的 所以要if else
void function1(Linklist str1,Linklist str2){
//两个源 两个工作指针 pa pb 一个目的 一个str1 尾插三个步骤 头插两个步骤
//13579 246810 合并为 12345678910 谁小插入谁
//97531 108642 合并为 10987654321 谁大插入谁 小结 要先插入那个源头里面那个最 递增谁小插入谁 递减谁大插入谁
Linklist pa=str1->next,pb=str2->next;
Linklist ra=str1;
while(pa&&pb){
if(pa->data<=pb->data){
ra->next=pa;
ra=pa;
pa=pa->next;
}else {
ra->next=pb;
ra=pb;
pb=pb->next;
}
}
if(pa)
pb=pa;
while(pb){
ra->next=pb;
ra=pb;
pb=pb->next;
}
ra->next=NULL;
free(str2);
}
int main()
{
int a[5];
for (int i=0;i<5;i++)
cin>>a[i];
Linklist first=new Node;
Linklist r=first;
for (int i=0;i<5;i++){
Linklist s=new Node;
s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
Linklist p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
int b[5];
for (int i=0;i<5;i++)
cin>>b[i];
Linklist first2=new Node;
Linklist r2=first2;
for (int i=0;i<5;i++){
Linklist s=new Node;
s->data=b[i];
r2->next=s;
r2=s;
}
r2->next=NULL;
p=first2->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
function1(first,first2);
p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
return 0;
}
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
typedef struct node{
int data;
struct node *next;
}Node,*Linklist;
//97531 108642 合并为 12345678910 两个头插 谁大插入谁 递增谁小插入谁 递减谁大插入谁
//如果 13579 246810 两个头插为 10987654321 还是谁小插入谁 good 懂了
void function2(Linklist str1,Linklist str2){
Linklist pa=str1->next,pb=str2->next;
str1->next=NULL;
Linklist u;
while(pa&&pb){
if(pa->data>=pb->data){//上面谁大谁先插入 这里谁大谁先插入
u=pa->next;
pa->next=str1->next;
str1->next=pa;
pa=u;
}else{
u=pb->next;
pb->next=str1->next;
str1->next=pb;
pb=u;
}
}
if(pa){
pb=pa;
}
while(pb){
u=pb->next;
pb->next=str1->next;
str1->next=pb;
pb=u;
}
free(str2);
}
int main()
{
int a[5];
for (int i=0;i<5;i++)
cin>>a[i];
Linklist first=new Node;
Linklist r=first;
for (int i=0;i<5;i++){
Linklist s=new Node;
s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
Linklist p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
int b[5];
for (int i=0;i<5;i++)
cin>>b[i];
Linklist first2=new Node;
Linklist r2=first2;
for (int i=0;i<5;i++){
Linklist s=new Node;
s->data=b[i];
r2->next=s;
r2=s;
}
r2->next=NULL;
p=first2->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
function2(first,first2);
p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
return 0;
}
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
typedef struct node{
int data;
struct node *next;
}Node,*Linklist;
// 97531 246810 合并成为 12345678910 第一条链头插 第二条链尾插
void function3(Linklist str1,Linklist str2){
Linklist pa=str1->next,pb=str2->next;
str1->next=NULL;
while(pa){
Linklist u=pa->next;
pa->next=str1->next;
str1->next=pa;
pa=u;
}
Linklist r=str1;
pa=str1->next;
while(pa&&pb){
//先就地逆置 然后 两个尾插
if(pa->data<=pb->data){
r->next=pa;
r=pa;
pa=pa->next;
} else {
r->next=pb;
r=pb;
pb=pb->next;
}
}
if(pa)
pb=pa;
while(pb){
r->next=pb;
r=pb;
pb=pb->next;
}
r->next=NULL;
free(str2);
}
int main()
{
int a[5];
for (int i=0;i<5;i++)
cin>>a[i];
Linklist first=new Node;
Linklist r=first;
for (int i=0;i<5;i++){
Linklist s=new Node;
s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
Linklist p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
int b[5];
for (int i=0;i<5;i++)
cin>>b[i];
Linklist first2=new Node;
Linklist r2=first2;
for (int i=0;i<5;i++){
Linklist s=new Node;
s->data=b[i];
r2->next=s;
r2=s;
}
r2->next=NULL;
p=first2->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
function3(first,first2);
p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
return 0;
}
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
typedef struct node{
int data;
struct node *next;
}Node,*Linklist;
//13579 108642 合并为12345678910 第一条链尾插 第二条链头插
void function4(Linklist str1,Linklist str2){
Linklist pa=str1->next,pb=str2->next;
Linklist ra=str1;
//str2就地逆置
str2->next=NULL;
while(pb){
Linklist u=pb->next;
pb->next=str2->next;
str2->next=pb;
pb=u;
}
pb=str2->next;//重新设置pb
while(pa&&pb){
if(pa->data<=pb->data){
ra->next=pa;
ra=pa;
pa=pa->next;
}else{
ra->next=pb;
ra=pb;
pb=pb->next;
}
}
if(pa)
pb=pa;
while(pb){
ra->next=pb;
ra=pb;
pb=pb->next;
}
ra->next=NULL;
free(str2);
}
int main()
{
int a[5];
for (int i=0;i<5;i++)
cin>>a[i];
Linklist first=new Node;
Linklist r=first;
for (int i=0;i<5;i++){
Linklist s=new Node;
s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
Linklist p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
int b[5];
for (int i=0;i<5;i++)
cin>>b[i];
Linklist first2=new Node;
Linklist r2=first2;
for (int i=0;i<5;i++){
Linklist s=new Node;
s->data=b[i];
r2->next=s;
r2=s;
}
r2->next=NULL;
p=first2->next;
while(p){
cout<<p->data;
p=p->next;
}
cout<<endl;
function4(first,first2);
p=first->next;
while(p){
cout<<p->data;
p=p->next;
}
return 0;
}