单向链表的C语言实现

单向链表的C语言实现

singlelinketlist.h

#ifndef SINGLE_LINKET_LIST_H__
#define SINGLE_LINKET_LIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

//单向链表结点

typedef int ETYPE;

//单向链表结点类型 
typedef struct Node{
	ETYPE elem;     //元素
	struct Node *next; //下一个节点的位置	
}SNode,*SLinketList; 

#define NODESIZE sizeof(struct Node)

SLinketList slinket_list_create(void); 
//判断单向链表是否为空 
bool slinket_list_is_empty(SLinketList head);
//单向链表中元素的个数
size_t slinket_list_size(SLinketList head);
//在指定位置pos插入一个元素elem  第一个位置默认为0 
int slinket_list_insert(SLinketList head,size_t pos,ETYPE elem);
//在单向链表前面插入一个元素elem
int slinket_list_insert_front(SLinketList head,ETYPE elem);
//在单向链表末尾插入一个元素elem
int slinket_list_insert_back(SLinketList head,ETYPE elem);
//删除指定位置pos的元素
int slinket_list_delete(SLinketList head,size_t pos,ETYPE *pelem);
//删除单向链表第一个元素
int slinket_list_delete_front(SLinketList head,ETYPE *pelem);
//删除末尾的元素
int slinket_list_delete_back(SLinketList head,ETYPE *pelem);
//获取指定位置pos的元素 
int slinket_list_get(SLinketList head,size_t pos,ETYPE *pelem);
//获取第一个元素
int slinket_list_get_front(SLinketList head,ETYPE *pelem);
//获取最后一个元素
int slinket_list_get_back(SLinketList head,ETYPE *pelem);
//根据值key来查找   返回-1表示没有该值  否则返回位置 
int slinket_list_find(SLinketList head,ETYPE *pelem);
//遍历单向链表
void slinket_list_travel(SLinketList head,void (*travel)(int)); 
//删除所有元素  清空所有元素 
void slinket_list_clear(SLinketList head);
//销毁单向链表
void slinket_list_destroy(SLinketList head); 
//单向链表逆序
void slinket_list_reverse(SLinketList head);
//获取倒数第n个元素
int slinket_list_get_last(SLinketList head,size_t pos,ETYPE *pelem);//[1,... 
// a1,a2,a3... an-1,an    a1,an,a2,an-1,a3,an-2,...
void slinket_list_reset_seq(SLinketList head);
// 按指定元素个数逆序  a1,a2,a3,a4,a5,a6,a7,a8   a3,a2,a1,a6,a5,a4,a8,a7
void slinket_list_reverse_by_count(SLinketList head,size_t count); 
#endif //SINGLE_LINKET_LIST_H__

singlelinketlist.c

#include "singlelinketlist.h"
SLinketList slinket_list_create(void){
	struct Node* head = (struct Node*)malloc(NODESIZE);//头结点  
	if(head==NULL){
		return NULL;
	}
	head->next = NULL;
	return head;
}
//判断单向链表是否为空 
bool slinket_list_is_empty(SLinketList head){//head 指针 指向头结点    *head头结点 
	return head->next == NULL; //(*head).next == NULL     
}
//单向链表中元素的个数
size_t slinket_list_size(SLinketList head){
	size_t size = 0;
	struct Node *node = head->next;//head指向头结点   head->next指向第一个结点 
	while(node != NULL){
		size++;
		node = node->next;//让node指针指向下一个节点 
	} 
	return size; 
}
//获取pos位置的前一个结点  如果pos过大,返回NULL 
static struct Node * slinket_list_get_prev_node(SLinketList head,size_t pos){
	struct Node *node = head; 
	size_t i;
	for(i=0;node!=NULL&&i<pos;i++){
		node = node->next;
	}
	return node;
} 
//在指定位置pos插入一个元素elem  第一个位置默认为0 
int slinket_list_insert(SLinketList head,size_t pos,ETYPE elem){	//要获取pos-1节点的指针  pos==0 头结点
	struct Node *prev = slinket_list_get_prev_node(head,pos);
	if(prev == NULL){
		return -1;
	}
	struct Node *node = (struct Node *)malloc(NODESIZE);
	if(node==NULL){
		return -2;
	}
	node->elem = elem;
	node->next = prev->next;
	prev->next = node;
	return 0;
}
//在单向链表前面插入一个元素elem
int slinket_list_insert_front(SLinketList head,ETYPE elem){
	struct Node *node = (struct Node *)malloc(NODESIZE);
	if(node==NULL){
		return -1;
	}
	node->elem = elem;
	node->next = head->next;
	head->next = node;
	return 0;
}
//在单向链表末尾插入一个元素elem
int slinket_list_insert_back(SLinketList head,ETYPE elem){
	//size_t size = slinket_list_size(head);
	//return slinket_list_insert(head,sie,elem);
	struct Node *last = head;
	while(last->next!=NULL){
		last = last->next;
	}
	//last->next == NULL
	//last->next = (struct Node *)malloc(NODESIZE);
	//last->next->elem = elem;  
	//last->next->next = NULL;
	struct Node *node = (struct Node *)malloc(NODESIZE);
	node->elem = elem;
	node->next = NULL;
	last->next = node;
	return 0;
}
//删除指定位置pos的元素
int slinket_list_delete(SLinketList head,size_t pos,ETYPE *pelem){
	struct Node *prev = slinket_list_get_prev_node(head,pos);
	if(prev == NULL || prev->next == NULL){
		return -1;
	}
	struct Node *curr = prev->next;
	prev->next = curr->next;
	*pelem = curr->elem;
	free(curr);
	return 0;
}
//删除单向链表第一个元素
int slinket_list_delete_front(SLinketList head,ETYPE *pelem){
	if(head->next == NULL){
		return -1;
	}
	*pelem = head->next->elem;
	struct Node *first = head->next;
	head->next = first->next;
	free(first);
	return 0;
}
//删除末尾的元素
int slinket_list_delete_back(SLinketList head,ETYPE *pelem){
	if(head->next == NULL){
		return -1;
	} 
	//size_t size = slinket_list_size(head);
	//return slinket_lsit_delete(head,size-1,pelem);
	struct Node *lastSec = head;
	while(lastSec->next->next != NULL){
		lastSec = lastSec->next;
	}
	//lastSec记录的是倒数第二个结点
	*pelem = lastSec->next->elem; 
	free(lastSec->next);//释放最后一个结点的内存 
	lastSec->next = NULL; 
	return 0; 
}
//获取指定位置pos的元素 
int slinket_list_get(SLinketList head,size_t pos,ETYPE *pelem){
	struct Node *node = slinket_list_get_prev_node(head,pos+1);
	if(node == NULL){
		return -1;
	}
	*pelem = node->elem;
	return 0;
}
//获取第一个元素
int slinket_list_get_front(SLinketList head,ETYPE *pelem){
	if(head->next == NULL){
		return -1;
	}
	*pelem = head->next->elem;
	return 0;
}
//获取最后一个元素
int slinket_list_get_back(SLinketList head,ETYPE *pelem){
	if(head->next == NULL){
		return -1;
	}
	struct Node *last = head->next;
	while(last->next != NULL){
		last = last->next; 
	}
	*pelem = last->elem;
	return 0;
}
//根据值key来查找   返回-1表示没有该值  否则返回位置 
int slinket_list_find(SLinketList head,ETYPE *pelem){
	struct Node *node = head->next;
	size_t i;
	for(i=0;node!=NULL;node=node->next,i++){
		if(node->elem == *pelem){
			return i;
		} 
	}
	return -1;
}
//遍历单向链表
void slinket_list_travel(SLinketList head,void (*travel)(int)){
	struct Node *node = head->next;
	while(node!=NULL){
		travel(node->elem);
		node = node->next;
	}
}

//删除所有元素  清空所有元素 
void slinket_list_clear(SLinketList head){
	struct Node *node,*next;
	for(node=head->next;node!=NULL;node=next){
		next = node->next;//提前保存node后面一个节点的位置 
		free(node);//释放node所指向的结点内存 
	}
	head->next = NULL;
}
//销毁单向链表
void slinket_list_destroy(SLinketList head){
	slinket_list_clear(head);
	free(head);//释放头结点的内存空间 
} 

//单向链表逆序
void slinket_list_reverse(SLinketList head){
	//没有结点 或者 只有一个结点 不需要做任何事情  
	if(head->next == NULL || head->next->next == NULL){
		return;
	}
	struct Node *prev = NULL;
	struct Node *curr = head->next;
	struct Node *next = NULL;
	while(curr!=NULL){
		next = curr->next; //保存当前结点的下一个结点的位置
		curr->next = prev; //逆转当前curr结点  指向原来的前结点
		prev = curr;
		curr = next; 
	}
	head->next = prev;
}
//获取倒数第n个元素
int slinket_list_get_last(SLinketList head,size_t pos,ETYPE *pelem){
	struct Node *front = head->next;
	struct Node *back = head->next;
	size_t i;
	for(i=1;front!=NULL&&i<pos;i++){
		front = front->next;//先让front先走pos-1步 
	}
	if(front == NULL){
		return -1;
	}
	while(front->next!=NULL){
		front = front->next;
		back = back->next; 
	}
	//front指向最后一个  back指向前面 pos-1
	*pelem = back->elem;
	return 0; 
}
// a1,a2,a3... an-1,an    a1,an,a2,an-1,a3,an-2,...
// 1 2 3 4 5 6 7 8 9 10   1 10 2 9 3 8 4 7 5 6

void slinket_list_reset_seq(SLinketList head){
	size_t size = slinket_list_size(head);
	if(size<=2)
		return;
	size_t i;
	struct Node *node = head->next;
	for(i=0;i<size/2;i++){
		node = node->next;
	}
	//node 作为头结点一样使用 
	slinket_list_reverse(node);
	struct Node *front = node->next, *back = head->next;
	node->next = NULL;
	node = head;
	bool flag = true;
	while(front!=NULL && back!=NULL){	
		node->next = back;
		back = back->next;
		node = node->next;
		node->next = front;
		front = front->next;
		node = node->next;				
xt = back;	
}

void slinket_list_reverse_by_count(SLinketList head,size_t count){
	struct Node *prev = NULL;
	struct Node *curr = head->next;
	struct Node *next = NULL;
	struct Node *last = head;//上次逆转之后的最后一个结点
	struct Node *first = NULL; 
	size_t i=0;
	while(curr != NULL){
		first = curr;//记录该次逆序的第一个结点  
		for(i=0;curr!=NULL&&i<count;i++){
			next = curr->next;
			curr->next = prev;
			prev = curr;
			curr = next;
		}
		last->next = prev;//上次逆转之后最后一个结点的下一个结点应该
		last = first; 
	}
	last->next = NULL;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值