C语言单链表

链表是通过一组任意的存储单元来存储线性表中的数据元素

定义节点如下:(语言是标准C语言)

#include <stdio.h>
#include <stdlib.h>
#define ERROR -1;//错误
#define TRUE 0;//正确
typedef struct node{

    ElemeteType data;//数据域
    
    struct node next;//指针域

}LNode,*LinkList;

单链表的基本操作

建立单链表(头插法),时间复杂度:O(n)

/**
  *   头插法
  */
LinkList Create_LinkList1(){
	LinkList H=(LinkList) malloc(sizeof(LNode));//生成头结点
	H->next=NULL;//建立一个空表
	LNode *s;
	int x;     //设数据元素的类型为int 
	scanf("%d",&x);
	while(x!=-1){
		s=(LinkList)malloc(sizeof(LNode));
		s->data=x;
		s->next=H->next;
		H->next=s;
		scanf("%d",&x);
	}
	return H;
}

建立单链表(尾插法),时间复杂度:O(n)

/**
  *   尾插法
  */
LinkList Create_LinkList2(){

	LinkList H=(LinkList)malloc(sizeof(LNode));//生成头结点
	H->next=NULL;
	LNode *s,*t;
	t=H;
	int x;     //设数据元素的类型为int 
	scanf("%d",&x);
	while(x!=-1){
		s=(LinkList)malloc(sizeof(LNode));
		s->data=x;
		s->next=t->next;
		t->next=s;
		t=s;  //t指向新的尾节点
		scanf("%d",&x);
	}
	return H;
}

求表长,时间复杂度O(n) 

/**
 * 求表长
 */
int Length_LinkList(LinkList H){

	LNode *p=H;
	int j=0;
	while(p->next!=null){
		p=p->next;
		j++;
	}
	return j;

}

查找操作(按序号查找),时间复杂度:O(n)

/**
 * 查找操作,按序号查找
 */
LinkList Get_LinkList(LinkList H,int k){

	LNode *p=H;
	int j=0;
	while(p->next!=NULL&&j<k){
		p=p->next;
		j++;
	}
	if(j==k){
		return p;
	}else{
		return NULL;
	}
}

查找操作(按值查找),时间复杂度:O(n)

/**
 * 查找操作,按值x查找
 */
LNode *Locate_LinkList(LinkList H,int x){
	LNode *p=H->next;
	while(p!=NULL&&p->data!=x){
		p=p->next;
	}
	return p;
}

单链表的插入操作,插入第i个位置,时间复杂度:O(n)

/**
 * 插入操作 时间复杂度 O(n)
 */
int Insert_LinkList(LinkList H,int i,int x){
	//在单链表H的第i个位置插入值为x的元素
	LNode *p,*s;
	p=Get_LinkList(H,i-1);//查找第i-1个节点(插入的位置,我们得知道这个节点的前驱节点)
	if(p=NULL){
		printf("插入的位置i错");
		return ERROR;
	}else{
		s=(LinkList)malloc(sizeof(LNode));//申请新节点
		s->data=x;
		s->next=p->next; //新节点插入在第i-1个节点后面
		p->next=s;
		return TRUE;
	}
}

单链表的删除操作,时间复杂度O(n)

/**
 * 删除节点 删除第i个节点
 */
int Del_LinkList(LinkList H,int i){
	LinkList p,q;
	p=Get_LinkList(H,i-1);//查找第i-1个节点
	if(p==NULL){
		printf("第i-1个节点不存在");
		return ERROR;
	}else{
		q=p->next;  //指向第i个节点
		p->next=q->next;  //从链表中删除
		free(q);  //释放*q
		return TRUE;
	}	
}

单链表的倒置,时间复杂度O(n)

思路:依次取出原链表中的每个节点,将其作为第一个节点插入新链表中,指针p用来指向当前节点,p为空时结束

/**
 * 单链表的倒置
 */
void Reverse(LinkList H){
	
	LNode *p,*q;
	p=H->next;//指向第一个数据元素(别忘了,我们之前是定义的带表头的哦)
	H->next=NULL;//把头节点卸下来
	while(p){
		q=p;
		p=p->next;//p指针一直指在旧链表上,直到"指"到最后为空
		//将当前节点插到头结点的后面,想不来的话回忆一下建立链表头插法你就了然了,
		//注意第一次插入的时候H->next是空的,也就是NULL
		q->next=H->next;
		H->next=q;
	}
}

如果大家还有点想不来倒置,我下面有个图解释了怎么倒置

看的顺序:黑色字体->红色字体->绿色字体

 

 

 

 

 

### C语言单链表的实现与操作 #### 基本概念 在C语言中,单链表是一种动态数据结构,由一系列节点组成。每个节点包含两部分:一部分用于存储数据,另一部分是一个指向下一个节点的指针。 为了便于操作,通常会引入头结点的概念[^2]。头结点不存储实际的数据,仅作为辅助节点存在,可以简化边界条件处理。 #### 头文件的引入 使用单链表时,需包含必要的头文件以支持内存分配和字符串操作等功能: ```c #include "stdio.h" #include "stdlib.h" // 提供 malloc() 和 free() #include "string.h" // 提供 strcpy() 等函数 ``` 这些头文件提供了创建、初始化以及销毁链表所需的工具[^1]。 #### 节点定义 单链表的核心在于其节点的设计。以下是典型的节点定义方式: ```c typedef struct LNode { int data; // 数据域 struct LNode *next; // 指向下一节点的指针 } LNode, *LinkList; ``` 这里 `LNode` 定义了一个节点类型,而 `LinkList` 是指向该类型的指针变量。 #### 创建单链表 可以通过多种方法来构建单链表,常见的有 **尾插法** 和 **头插法**: ##### 尾插法 尾插法是从链表头部开始逐步插入新节点到链表末尾的方式。 ```c void CreateList_Tail(LinkList &L, int n) { LinkList p, r = L; // 初始化工作指针r为头结点 for(int i=0;i<n;i++) { p = (LinkList)malloc(sizeof(LNode)); scanf("%d", &(p->data)); // 输入数据 p->next = NULL; r->next = p; // 插入到最后一个节点之后 r = p; // 更新最后一个节点位置 } } ``` ##### 头插法 头插法则是在每次插入时都将新节点放置于当前链表的第一个有效节点之前。 ```c void CreateList_Head(LinkList &L, int n){ LinkList p; for(int i=0;i<n;i++){ p=(LinkList)malloc(sizeof(LNode)); scanf("%d",&(p->data)); // 输入数据 p->next=L->next; // 新节点连接至原首节点前 L->next=p; // 修改头结点指向新的第一个节点 } } ``` #### 查找操作 对于按位查找的功能,在已知索引的情况下可以直接遍历链表找到对应位置上的元素[^3]。时间复杂度一般为 O(n),其中 n 代表链表长度。 ```c int GetElem(LinkList L, int index){ if(index<0 || !L->next)return -1; // 判断输入合法性 LinkList p = L->next; while(p && --index>0)p=p->next; return p?p->data:-1; } ``` #### 删除操作 删除指定位置处的节点需要先定位目标节点及其前置节点,随后调整指针关系完成移除过程。 ```c bool DeleteElem(LinkList &L,int pos){ if(pos<=0||!L->next)return false; LinkList pre=L,p=L->next; for(int i=1;p&&i<pos;i++,pre=p,p=p->next); if(!p)return false; pre->next=p->next; free(p);return true; } ``` #### 存储应用实例——学生信息管理 利用上述基础功能可进一步扩展应用于具体场景下,比如建立一个简单的学生信息系统[^4]: ```c struct Student{ char name[20]; int score; struct Student *next; }; // 添加学生记录... ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值