头插法和尾插法创建链表 链表的11种常用操作(详解)

尾插法

#include<stdio.h>
#include<malloc.h>
//尾插法 
struct list{
	int data;
	struct list *next;
};

typedef struct list node;
typedef node *link;

int main(){
	link rail,head;
	int i,num;
	//输入链表中的元素
	head = (link) malloc (sizeof(node));
	rail = head;  //head为头指针
	printf("input 5 numbers: \n");
	for(int i =0;i < 5;i++){
		scanf("%d",&num);
		link temp = (link) malloc(sizeof(node));
		temp->data = num;
		rail->next = temp;		
		rail = temp; 				//rail始终指向最后一个结点 
	}
	
	rail->next = NULL;      //尾结点指针设为空 
	
	head = head->next;		//跳过头指针的数值域,因为头指针没有数值 
	//输出链表
	while (head != NULL)
	{
		printf("%d\n", head->data);
		head = head->next;
	}
	return 0;
} 
	

头插法

#include<stdio.h>
#include<malloc.h>

struct list{
	int data;
	struct list *next;
};

typedef struct list node;
typedef node *link;

int main(){
	link ptr,head;
	int i,num;
	//输入链表中的元素
	head = (link) malloc (sizeof(node));  //head为头指针
	head->next = NULL;
	
	printf("input 5 numbers: \n");
	for(int i = 0;i < 5;i++){
		scanf("%d",&num);
		ptr = (link) malloc(sizeof(node));
		ptr->data = num;
		ptr->next = head->next;      //先让新结点指向头指针指向的的结点(空结点) 
		head->next = ptr;			//然后才能让头指针指向新结点. 
	}
	
	head = head->next;  //跳过头结点输出,因为头结点data域没有值 
	
	//输出链表
	while (head != NULL)
	{
		printf("%d\n", head->data);
		head = head->next;
	}
	return 0;
} 
	

单链表的常用操作

//1.单链表的初始化
//2.判空操作
//3.遍历操作
//4.求单链表长度
//5.按值查找
//6.按位查找
//7.插入操作
//8.1根据a[n]元素建立单链表 :头插法
//8.2根据a[n]元素建立单链表 :尾插法
//9.删除操作
//10.销毁单链表
//11.1 反转链表 方法1
//11.2 反转链表 方法2

#include<stdio.h>
#include<malloc.h>
#include<bits/stdc++.h>
using namespace std;

typedef int DataType;
typedef struct Node{
	DataType data;
	struct Node *next;
}Node;

//1.单链表的初始化 
Node *InitList(){
	Node * first = (Node *)malloc(sizeof(Node)); //生成头结点 
	first->next = NULL;   //头结点指针域置空
	return first; 
}

//2.判空操作 
int Empty(Node * first){
	if(first->next == NULL) return 1;
	else return 0;
} 

//3.遍历操作
void PrintList(Node *first){
	Node *p = first->next; 		//工作指针p初始化 
	while(p!=NULL){
		printf("%d ",p->data);//输出结点的数据域,假设为int型
		p = p->next;         //工作指针p后移,注意不能写成p++ 
	}
	printf("\n");
}

//4.求单链表长度
int Length(Node *first){
	Node *p = first->next; //工作指针p初始化 
	int count = 0; //累加器count初始化 
	while(p!=NULL){
		p = p->next;
		count ++;
	}
	return count;	
} 

//5.按值查找
int Locate(Node *first,DataType x){
	Node *p = first->next; //工作指针p初始化 
	int count = 1; //累加器count初始化 
	while (p!=NULL){
		if(p->data == x) return count; //查找成功,结束函数并返回序号
		p = p->next; 
		count ++;
	} 
	return 0; //退出循环表示查找失败 
} 

//6.按位查找
int Get(Node *first,int i,DataType *ptr){
	Node *p = first->next;
	int count = 1;
	while(p!=NULL&&count<i){
		p = p->next;
		count ++;
	}
	if(p == NULL) {printf("位置错误,查找失败\n");return 0;}
	else{* ptr = p->data; return 1;}
}

//7.插入操作
int Insert(Node *first,int i,DataType x){
	Node *s = NULL,*p = first; //工作指针p初始化为指向头节点
	int count = 0;
	while(p!=NULL && count < i-1){//查找第i-1个结点 
		p = p->next;
		count++; 
	}
	if(p == NULL){printf("位置错误,插入失败\n"); return 0;}
	else{
		s = (Node *)malloc(sizeof(Node));
		s->data = x;
		s->next = p->next; //申请一个结点,数据域为x 
		p->next = s; //将结点s插入到结点p之后,注意"先右后左" 
		return 1;
	}
} 

//8.1根据a[n]元素建立单链表 :头插法
Node * CreatList_H(DataType a[],int n){
	Node *s = NULL;
	Node *first = (Node*)malloc(sizeof(Node));
	first->next = NULL; //初始化头节点 
	for(int i = 0;i < n;i ++){
		s = (Node *)malloc(sizeof(Node));
		s->data = a[i]; //为每个数组元素建立一个结点 
		s->next = first->next; //将结点s插入到头节点之后 
		first->next = s; 
	}
	return first;
} 

//8.2根据a[n]元素建立单链表 :尾插法
Node * CreatList_R(DataType a[],int n){
	Node *s = NULL,*last = NULL;
	Node *first = (Node *)malloc(sizeof(Node)); //生成头节点
	last = first; //尾指针初始化
	for(int i = 0;i < n;i++){
		s = (Node *)malloc(sizeof(Node));
		s->data = a[i]; //为每个数组元素建立一个结点 
		last->next = s; //将结点s插入到终端结点之后 
		last = s; //尾指针后移,始终指向终端结点 
	} 
	last->next = NULL; //单链表建立完毕,将终端结点的指针域置为空 
	return first;
} 

//9.删除操作
int Delete(Node *first,int i,DataType *ptr){
	Node *p = first,*q = NULL; 
	int count = 0;
	DataType x;
	while(p!=NULL && count < i-1){	//查找第i-1个结点 
		p = p->next; 				//p最终指向第i-1个结点 
		count ++;
	}
	if(p==NULL || p->next==NULL){	//p结点或p的后继结点不存在 
		printf("位置错误,删除失败\n"); return 0; 
	}else{
		q = p->next; 				//q指向p的后一个结点,即第i个结点 
		* ptr = q->data; 			//存储被删除结点和被删除的元素
		//printf("q->data=%d\n",q->data);
		p->next = q->next; //摘链 
		free(q);
		return 1; 
	}
}

//10.销毁单链表
void DestroyList(Node *first){
	Node *p = first;
	while(first!=NULL){ //依次释放每一个结点,包括头结点 
		first = first->next;
		free(p);
		p = first;
	}
} 

/* 11.1 反转链表  方法1 
// 图文解释: https://blog.csdn.net/qq_42351880/article/details/88637387
Node *reverseList(Node* head) {
	Node *newHead = NULL;
	Node *node;
	while (head != NULL) {
		//1. 对之前的链表做头删
		node = head;
		head = head->next;
		
		//2. 对新链表做头插
		node->next = newHead;
		newHead = node;
	}
	return newHead;
}
*/ 

//11.2 反转链表 方法2 
Node *reverseList(Node* head) {
	if (head == NULL) {
		return NULL;
	}
	Node *p0 = NULL;
	Node *p1 = head;
	Node *p2 = head->next;
	while (p1 != NULL) {
		p1->next = p0;
		p0 = p1;
		p1 = p2;
		if (p2 != NULL) {
			p2 = p2->next;
		}
	}
	return p0;
}


int main(){
	int r[5] = {1,2,3,4,5},i,x;
	Node *first = NULL;
	Node *head = NULL;
	first = NULL;
	
	first = CreatList_R(r,5); 		//根据a[n]元素建立单链表 :尾插法
	printf("当前线性表的数据为: ");
	PrintList(first); 				//尾插法输出当前线性表为1 2 3 4 5,头插法顺序相反 
	
	Insert(first,2,8); 				//在第二个位置插入值为8的结点
	printf("执行插入后数据为:");
	PrintList(first); 				//输出插入后链表 1 8 2 3 4 5
	
	printf("当前链表长度为: %d\n",Length(first)); //输出链表长度为6
	
	printf("请输入查找的元素值: "); 
	scanf("%d",&x);
	head = first;					//head指向first链表 
	i = Locate(head,x); 	/*cout<<i;  测试是否返回值成功 */
	if(i != NULL) printf("元素%d的位置为:%d\n",x,i);
	else printf("单链表中没有元素%d\n",x);
	
	printf("请输入要删除第几个元素: ");
	scanf("%d",&i);
	if(Delete(head,i,&x) == 1){//删除第i个元素 
		printf("删除的元素值是%d,执行删除操作后数据为:\n",x);
		PrintList(head);
	}else printf("删除失败\n");

	printf("执行逆置后数据为:");
	head = reverseList(first);		//逆转first链表 
	while( Length(head) ){			//输出逆转链表,因为逆转后以后一个结点类似头结点,值域为空.所以不能用常规的打印方法,否则会多打印出一个值 
		printf("%d ",head->data);
		head = head->next;
	}
	
	DestroyList(head); //释放单链表
	return 0;
	
}
	

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值