文章目錄
- 一、前言
- 二、有序單連結清單去重
-
- 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;
}