单链表的实现

节点结构体的创建

typedef int data_t;
typedef struct node {
	data_t data;
	struct node *next;
}linknode,*linklist;

操作函数

linklist node_create(void);						//创建头节点 
void head_insert(linklist L, data_t arg);		//头部插入节点
void tail_insert(linklist L, data_t arg);		//尾部插入节点
void head_delete(linklist L);					//头部删除节点
void tail_delete(linklist L);					//尾部删除节点
void post_delete(linklist L, int postition);	//在指定位置删除节点
void list_sort(linklist L);						//排序(通过冒泡实现)
linklist list_clear(linklist L);				//清除链表并释放内存
void list_show(linklist L);						//遍历链表

创建一个新节点

linklist node_create(void) {
	linklist L;			//先定义一个结构体指针
	L = (linklist)malloc(sizeof(linknode));  //给头节点申请内存空间
	if (L == NULL) {
		perror("malloc");
		return;
	}
	L->next = NULL;  //头节点置空
	L->data = 0;	 //头节点数据域用来存放节点数(不包含头节点)
	return L;		 //返回头节点地址
}

从头部插入一个节点

void head_insert(linklist L, data_t arg) {
	/*若链表中只有一个头节点,那么头部插入就会失败*/
	if (L->next == NULL) {
		printf("head_insert failed:list is empty\n");
		return;
	}
	
	linklist temp;			//创建一个新节点temp用来存放要插入的数据
	if ((temp = (linklist)malloc(sizeof(linknode))) == NULL) { //给新节点申请内存
		perror("malloc in head_insert");
		return;
	}
	L->data++;				//每执行一次插入函数,头节点的data就会加一,方便用来计数链表中的节点数
	temp->next = L->next;	//必须先将第二个节点接到temp后面,不然第二个节点一旦与头节点断开,将会丢失找不到
	L->next = temp;			//将temp接到头节点的后面
	temp->data = arg;		//存入数据
}

从尾部插入一个节点

void tail_insert(linklist L, data_t arg) {
	linklist temp;   //temp是用来存放插入数据arg的节点
	linklist temp2;	 //temp2是用来扫描链表结尾的临时节点
	temp2 = L;
	if ((temp = (linklist)malloc(sizeof(linknode))) == NULL) {  //申请内存空间
		perror("malloc in tail_insert()");
		return;
	}
	while (temp2->next != NULL) {
		temp2 = temp2->next;     //temp2指向下一个节点,直到达到链表尾部
	}
	L->data++;					 //每执行一次插入函数,头节点的data就会加一,方便用来计数链表中的节点数
	/*将目标节点temp接到链表尾部*/
	temp2->next = temp;			 
	temp->data = arg;
	temp->next = NULL;
}

从头部删除一个节点

void head_delete(linklist L) {
	if (L->next == NULL) {
		printf("head_delete failed:list is empty\n");
		return;
	}
	linklist temp;
	linklist temp2;

	temp = L->next;           //存放第一个节点地址
	L->next = L->next->next;  //将第二个节点接在头节点后面,成为第一个节点,之前的第一个节点将游离
	free(temp);				  //释放之前的第一个节点
	temp = NULL;			  //置空
	L->data--;				  //链表节点数减一
}

从尾部删除一个节点

void tail_delete(linklist L) {
	if (L->next == NULL) {
		printf("delete failed:list is empty\n");
		return;
	}
	linklist temp;
	linklist temp2;
	temp = L;
	while (temp->next->next != NULL) {  //遍历到倒数第二个节点
		temp = temp->next;
	}

	temp2 = temp->next;					//temp2存放要删除的节点
	free(temp2);						//释放删除的节点内存
	temp->next = NULL;					
	L->data--;
}

删除指定位置的节点

void post_delete(linklist L, int postition) {
	if (L->next == NULL) {
		printf("post_delete failed:list is empty\n");
		return;
	}
	if (postition <= 0 || postition > L->data) {		//判断pos是否超出限制
		printf("post_delete failed:postition is out of limit\n");
		return;
	}
	linklist temp;
	linklist temp2;
	int i;
	temp = L;
	for (i = 0; i < postition - 1; i++) {		//遍历到目标节点的前一个节点
		temp = temp->next;
	}
												//此时temp存放的是目标节点的前一个节点
	temp2 = temp->next;							//temp2存放目标节点
	temp->next = temp->next->next;				//将要删除的节点的下一个节点接到temp的后面,目标节点游离
	free(temp2);								//释放目标节点
	L->data--;									//节点数减一
}

排序

void list_sort(linklist L) {
	linklist p = NULL;
	linklist q = NULL;
	linklist temp = NULL;
	int i, j; 

	/*这里使用基础的冒泡排序*/
	for (i = 0; i < L->data - 1; i++) {
		temp = L;				//外层循环执行一次,temp重新指回头节点
		p = temp->next;			//p指向第一个节点
		q = p->next;			//q指向p的下一个节点
		for (j = 0; j < L->data - i - 1; j++) {
			if (p->data > q->data) {
				/*交换两个节点的位置*/
				p->next = q->next;
				q->next = p;
				temp->next = q;				
			}
			/*内层循环执行一次,temp向后移动一个节点*/
			temp = temp->next;
			p = temp->next;
			q = p->next;
		}
	}
}

清空并释放链表

linklist list_clear(linklist L) {
	linklist p = NULL;
	if (L == NULL)
		return NULL;

	p = L;
	while (L != NULL) {   //逐个遍历
		p = L;			  //p存放L的地址
		L = L->next;      //L指向下一节点(L将逐一指向后续节点)
		free(p);		  //即释放原来的L
	}
	printf("\nclear successfully\n");
	return NULL;		  //此时包括头节点L在内的所有节点都已经释放
}

遍历链表

void list_show(linklist L) {
	if (L->next == NULL) {
		printf("show failed : list is empty\n");
		return;
	}
	linklist temp;
	temp = L;			//temp指向头节点
	while (temp->next != NULL) {		//遍历到最后一个节点
		temp = temp->next;				//temp向后移动
		printf("%d ", temp->data);		//之所以先移动后打印是因为temp最初指向头节点,而头节点data不必打印,因此从头节点后面的第一个节点开始打印数据
	}
	puts("");
}

完整程序

#include<stdio.h>
#include<malloc.h>
typedef int data_t;

/*节点结构体*/
typedef struct node {
	data_t data;
	struct node *next;
}linknode,*linklist;

linklist node_create(void);						//创建头节点 
void head_insert(linklist L, data_t arg);		//头部插入节点
void tail_insert(linklist L, data_t arg);		//尾部插入节点
void head_delete(linklist L);					//头部删除节点
void tail_delete(linklist L);					//尾部删除节点
void post_delete(linklist L, int postition);	//在指定位置删除节点
void list_sort(linklist L);						//排序(通过冒泡实现)
linklist list_clear(linklist L);				//清除链表并释放内存
void list_show(linklist L);						//遍历链表

int main() {
	linklist H = NULL;
	int buf[128] = { 0 };
	int i = 0, j = 0;
	H = node_create();     //创建一个头节点
	printf("input : ");
	while (1) {
		j = scanf("%d", &buf[i]);
		tail_insert(H, buf[i]);
		if (getchar() == '\n')break;
		i++;
	}
	printf("numbers : ");
	list_show(H);
	list_sort(H);
	printf("sort : ");
	list_show(H);
	return 0;
}

linklist node_create(void) {
	linklist L;			//先定义一个结构体指针
	L = (linklist)malloc(sizeof(linknode));  //给头节点申请内存空间
	if (L == NULL) {
		perror("malloc");
		return;
	}
	L->next = NULL;  //头节点置空
	L->data = 0;	 //头节点数据域用来存放节点数(不包含头节点)
	return L;		 //返回头节点地址
}

void head_insert(linklist L, data_t arg) {
	/*若链表中只有一个头节点,那么头部插入就会失败*/
	if (L->next == NULL) {
		printf("head_insert failed:list is empty\n");
		return;
	}
	
	linklist temp;			//创建一个新节点temp用来存放要插入的数据
	if ((temp = (linklist)malloc(sizeof(linknode))) == NULL) { //给新节点申请内存
		perror("malloc in head_insert");
		return;
	}
	L->data++;				//每执行一次插入函数,头节点的data就会加一,方便用来计数链表中的节点数
	temp->next = L->next;	//必须先将第二个节点接到temp后面,不然第二个节点一旦与头节点断开,将会丢失找不到
	L->next = temp;			//将temp接到头节点的后面
	temp->data = arg;		//存入数据
}

void tail_insert(linklist L, data_t arg) {
	linklist temp;   //temp是用来存放插入数据arg的节点
	linklist temp2;	 //temp2是用来扫描链表结尾的临时节点
	temp2 = L;
	if ((temp = (linklist)malloc(sizeof(linknode))) == NULL) {  //申请内存空间
		perror("malloc in tail_insert()");
		return;
	}
	while (temp2->next != NULL) {
		temp2 = temp2->next;     //temp2指向下一个节点,直到达到链表尾部
	}
	L->data++;					 //每执行一次插入函数,头节点的data就会加一,方便用来计数链表中的节点数
	/*将目标节点temp接到链表尾部*/
	temp2->next = temp;			 
	temp->data = arg;
	temp->next = NULL;
}

void head_delete(linklist L) {
	if (L->next == NULL) {
		printf("head_delete failed:list is empty\n");
		return;
	}
	linklist temp;
	linklist temp2;

	temp = L->next;           //存放第一个节点地址
	L->next = L->next->next;  //将第二个节点接在头节点后面,成为第一个节点,之前的第一个节点将游离
	free(temp);				  //释放之前的第一个节点
	temp = NULL;			  //置空
	L->data--;				  //链表节点数减一
}

void tail_delete(linklist L) {
	if (L->next == NULL) {
		printf("delete failed:list is empty\n");
		return;
	}
	linklist temp;
	linklist temp2;
	temp = L;
	while (temp->next->next != NULL) {  //遍历到倒数第二个节点
		temp = temp->next;
	}

	temp2 = temp->next;					//temp2存放要删除的节点
	free(temp2);						//释放删除的节点内存
	temp->next = NULL;					
	L->data--;
}

void post_delete(linklist L, int postition) {
	if (L->next == NULL) {
		printf("post_delete failed:list is empty\n");
		return;
	}
	if (postition <= 0 || postition > L->data) {		//判断pos是否超出限制
		printf("post_delete failed:postition is out of limit\n");
		return;
	}
	linklist temp;
	linklist temp2;
	int i;
	temp = L;
	for (i = 0; i < postition - 1; i++) {		//遍历到目标节点的前一个节点
		temp = temp->next;
	}
												//此时temp存放的是目标节点的前一个节点
	temp2 = temp->next;							//temp2存放目标节点
	temp->next = temp->next->next;				//将要删除的节点的下一个节点接到temp的后面,目标节点游离
	free(temp2);								//释放目标节点
	L->data--;									//节点数减一
}

void list_sort(linklist L) {
	linklist p = NULL;
	linklist q = NULL;
	linklist temp = NULL;
	int i, j; 

	/*这里使用基础的冒泡排序*/
	for (i = 0; i < L->data - 1; i++) {
		temp = L;				//外层循环执行一次,temp重新指回头节点
		p = temp->next;			//p指向第一个节点
		q = p->next;			//q指向p的下一个节点
		for (j = 0; j < L->data - i - 1; j++) {
			if (p->data > q->data) {
				/*交换两个节点的位置*/
				p->next = q->next;
				q->next = p;
				temp->next = q;				
			}

			/*内层循环执行一次,temp向后移动一个节点*/
			temp = temp->next;
			p = temp->next;
			q = p->next;
		}
	}
}

linklist list_clear(linklist L) {
	linklist p = NULL;
	if (L == NULL)
		return NULL;

	p = L;
	while (L != NULL) {   //逐个遍历
		p = L;			  //p存放L的地址
		L = L->next;      //L指向下一节点(L将逐一指向后续节点)
		free(p);		  //即释放原来的L
	}
	printf("\nclear successfully\n");
	return NULL;		  //此时包括头节点L在内的所有节点都已经释放
}

void list_show(linklist L) {
	if (L->next == NULL) {
		printf("show failed : list is empty\n");
		return;
	}
	linklist temp;
	temp = L;			//temp指向头节点
	while (temp->next != NULL) {		//遍历到最后一个节点
		temp = temp->next;				//temp向后移动
		printf("%d ", temp->data);		//之所以先移动后打印是因为temp最初指向头节点,而头节点data不必打印,因此从头节点后面的第一个节点开始打印数据
	}
	puts("");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值