继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

【国庆出大力】c/c++实现单链表的创建、插入、删除、逆置、归并

mytac
关注TA
已关注
手记 9
粉丝 6416
获赞 192

因为本人要准备考研了,关于前端的东西占比会变少,不过还是和计算机相关的内容,大家多了解一点也无妨。最近在复习901数据结构与算法设计,当然也是各大公司笔试题的一部分。主要代码都是c/c++,因为四年没写了,突然上手写的很渣==如果有需要改进的地方请留言,我看到会及时的修改。
有图片上传不成功点击github原文

demo

创建链表

头插入

#include<iostream>
#include "stdio.h"
#include "stdlib.h"
using namespace std;

struct LNode{
	int data; // 数据域 
	LNode *next; // 指向自身的指针域 
};
typedef LNode *LinkList; 

LinkList createLinkList Head(){
LinkList L;
LinkList p;
int x;
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL;
cin>> x;
while(x!=0) {
	p=(LinkList)malloc(sizeof(LNode));
	p->data=x;
	p->next=L->next;
	L->next=p;
	cin>>x;
};
return L;
}

int main(){
createLinkListHead();
}

查找

按序号查

LinkList findNodeByOrder(LinkList L,int target){
	LinkList p=L;
	int i=0;
	while(i<target&&p->next!=NULL){
		p=p->next;
		i++;
	}
	if(i==target){
		return p;
	}
	return NULL;
}

按数据查

int findNodeByValue(LinkList L,int target){
	LinkList p=L;
	while(p->data!=target&&p->next!=NULL){
		p=p->next;
	}
	
	return p->data;
}

插入

指定在某个序号前插入某个值

LinkList insertBefore(LinkList L,int s,int target){ // target为指定插入位置的数据域为s的节点 
	LinkList p=L;
	LinkList newNode=(LinkList)malloc(sizeof(LNode));
	newNode->data=s;
	int i=0; 
	if(target<1){
		printf("参数target错误"); 
		exit(1);
	}
	while(i<target-1){
		i++;
		p=p->next;
	}
		// 现在的p是目标节点的前驱 
		newNode->next=p->next;
		p->next=newNode;
	return L;
}

删除

删除单链表第i个节点

LinkList deleteByOrder(LinkList L,int i){
	// 仍然是找前驱 
	LinkList p=L;
	LinkList q;
	int j=0;
	while(j<i-1){
		p=p->next; 
		j++;
	}
	if(p==NULL||j>i-1){
		printf("参数i错误");
		exit(1);
	} 
	q=p->next; // 目标节点
	p->next=q->next;
	free(q);
	return L;
}

双向链表

创建双向链表

struct DuLNode{
	int data;
	DuLNode *next;
	DuLNode *prior;
}; 
typedef DuLNode *DuLinkList;

DuLinkList createDoubleLinkList(){
	DuLinkList head,L;
	DuLinkList p;
	int x;
	L=(DuLinkList)malloc(sizeof(DuLNode));
	head=L;
	cin>>x;
	while(x!=0){
		p=(DuLinkList)malloc(sizeof(DuLNode));
		p->data=x;
		p->next=NULL;
		p->prior=L;
		L->next=p;
		L=p; 
		cin>>x;
	}
	return head;
}

双向链表插入节点

在双向链表第i个节点前插入数据域为x的节点。还是先连后断,因为是双向链表有前驱指针不用找第i+1个元素了。先把新节点s的前驱后继连上,然后断开目标节点p的前驱节点的后继指针,将他连到s上,然后再操作目标节点p的前驱指向新节点!!

DuLinkList DuLinkInsert(DuLinkList L,int i,int x){
	DuLinkList head,s,p;
	int n=0;
	p=L;
	head=L;
	s=(DuLinkList)malloc(sizeof(DuLNode));
	s->data=x; 
	while(n<i){
		p=p->next;
		n++;
	}
	if(i==n){
		s->next=p;
		s->prior=p->prior;
		p->prior->next=s;
		p->prior=s;
		return head;
	}else{
		cout<<"参数i错误"<<endl;
		exit(1);
	}
}

双链表删除节点

还是删除i位置的节点p,p的前驱节点的后继与p的后继相同,p的后继节点的前驱与p的前驱指针相连,释放p。

DuLinkList DuLinkDelete(DuLinkList L,int i){
	DuLinkList head,p;
	int n=0;
	p=L;
	head=L;
	while(n<i){
		p=p->next;
		n++;
	}
	if(i==n){
		p->prior->next=p->next;
		p->next->prior=p->prior;
		free(p);
		return head;
	}else{
		cout<<"参数i错误"<<endl;
		exit(1);
	}
}

扩展

合并两个链表

Node* mergelistByOrder(Node *l1,Node *l2){
	Node *head,*L;
	L=new Node;
	L->next=NULL;
	L->data=0;
	head=L;
	while(l1&&l2){
		if(l1->data<l2->data){
			L->next=l1;
			l1=l1->next;
		}else{
			L->next=l2;
			l2=l2->next;	
		}
		L=L->next;
	}
	if(l1){
		L->next=l1;
	}
	if(l2){
		L->next=l2;
	}

	return head->next;
}

链表原地逆置

原地逆置需要两个指针p,q,和一个临时指针t。q是p的后继,然后将q->next指向p。最终循环完要先断开头节点与这个链表之间的后继关系,将头节点的后继指向p。具体见这个图示->链表原地反转

Node* reverse(Node* L){
	Node *p,*q,*t,*head;
	head=L;
	p=head->next;
	q=head->next->next;
	while(q!=NULL){
	t = q->next;  
	q->next = p;  
	p = q;  
	q = t;
	}
	head->next->next=NULL;
	head->next=p;
	return head;
}

两个升序链表,降序合并

  1. 第一个方法是将上面两个方法结合起来,先按顺序合并,然后逆置。
  2. 第二个方法是通过头插法,选择最小的先插入。
Node* mergelistByDescOrder(Node *l1,Node *l2){
	Node *L,*head,*t,*q;
	L=new Node();
	head=L;
	while(l1&&l2){
		if(l1->data<l2->data){
			t=l1;
			l1=l1->next;
		}else {
			t=l2;
			l2=l2->next;
		}
		t->next=L->next;
		L->next=t;
		//L=t;
		t=NULL; 
	}
	// 如果l1和l2循环之后还有剩余的节点,按顺序依次添加到头节点之后
	if(l1){
		t=l1;
	}
	if(l2){
		t=l2;
	}
	while(t){
		q=t;
		t=t->next;
		q->next=L->next;
		L->next=q;
	}
	return head->next;
} 
打开App,阅读手记
6人推荐
发表评论
随时随地看视频慕课网APP