单链表

链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存放到下一个节点的指针(Pointer)。使用链表结构可以克服数组需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。

链表有很多种不同的类型:单向链表,双向链表以及循环链表

本章主要讲解单向链表

1、插入

其实现的过程考虑边界情况:
1)当L为空;
2)在链表的头部插入;
3)在链表的中间插入(包括在链表尾部插入的情况)。

2、删除

删除和插入是一个相反的过程,一般需要先找到删除结点的前驱(prev)
1)当L为空;
2)删除链表的首结点;
3)删除链表的中间结点(包括删除链表尾结点的情况)。 

链表形态

操作过程

 

// sll.h
#ifndef _MY_SSL_H
#define _MY_SSL_H

/* singly linked list */
typedef struct singly_linked_list_node {
	struct singly_linked_list_node *next;
} SSL_NODE;

typedef struct singly_linked_list {
	SSL_NODE *first;
	SSL_NODE *last;
} SSL_LIST;

void list_init(SSL_LIST *list);

void list_insert_head(SSL_LIST *list, SSL_NODE *node);

void list_insert_tail(SSL_LIST *list, SSL_NODE *node);

void list_insert_after(SSL_LIST *list, SSL_NODE *pos, SSL_NODE *node);

void list_delete_head(SSL_LIST *list);

void list_delete(SSL_LIST *list, SSL_NODE *node);

int list_get_num(SSL_LIST *list);

#endif

// sll.c
#include <stdlib.h>
#include "sll.h"

void list_init(SSL_LIST *list)
{
	list->first = NULL;
	list->last = NULL;
}

void list_insert_head(SSL_LIST *list, SSL_NODE *node)
{
	if (node == NULL) {
		return;
	}

	node->next = list->first;
	list->first = node;

	if (list->last == NULL) {
		list->last = node;
	}
}

void list_insert_tail(SSL_LIST *list, SSL_NODE *node)
{
	if (node == NULL) {
		return;
	}

	if (list->last != NULL) {
		list->last->next = node;
	} else {
		list->first = node;
	}

	list->last = node;
}

void list_insert_after(SSL_LIST *list, SSL_NODE *prev, SSL_NODE *node)
{
	if (prev == NULL || node == NULL) {
		return;
	}

	node->next = prev->next;
	prev->next = node;

	if (list->last == prev) {
		list->last = node;
	}
}

void list_delete_head(SSL_LIST *list)
{
	SSL_NODE *head = list->first;

	if (list->first != NULL) {
		list->first = head->next;
		head->next = NULL;

		if (list->first == NULL) {
			list->last = NULL;
		}
	}
}

SSL_NODE *list_find_prev(SSL_LIST *list, SSL_NODE *node)
{
	SSL_NODE *iter = NULL;

	/* 前驱不存在 */
	if ((list->first == NULL) || (list->first == node)) {
		return NULL;
	}

	iter = list->first; /* iter不为NULL */
	while (iter->next != NULL) {
		if (iter->next == node) {
			break;
		}

		iter = iter->next;
	}

	return iter;
}

void list_delete(SSL_LIST *list, SSL_NODE *node)
{
	SSL_NODE *prev = NULL;

	if (node == NULL) {
		return NULL;
	}

	prev = list_find_prev(list, node);
	if (prev == NULL) { 
		if (list->first == node) { /* first node */
			list->first = node->next;
			node->next = NULL;
		}
	} else {
		prev->next = node->next;
		node->next = NULL;
	}

	if (list->last == node) { /* last node */
		list->last = prev;
	}
}

void list_delete2(SSL_LIST *list, SSL_NODE *node)
{
	SSL_NODE *prev = NULL;

	if ((list->first == NULL) || (node == NULL)) {
		return NULL;
	}

	if (list->first == node) {	/* first node */
		list->first = node->next;
		node->next = NULL;

		if (list->last == node) { /* last node */
			list->last = NULL;
		}
	} else {
		prev = list->first;
		while (prev->next != NULL) {
			if (prev->next == node) {
				prev->next = node->next;
				node->next = NULL;

				if (list->last == node) {
					list->last = prev;
				}

				break;
			}

			prev = prev->next;
		}
	}
}

int list_get_num(SSL_LIST *list)
{
	int num = 0;
	SSL_NODE *iter = list->first;

	while (iter != NULL) {
		num++;
		iter = iter->next;
	}

	return num;
}

#pragma once

#ifndef _MY_SSL2_H
#define _MY_SSL2_H

/* singly linked list */
typedef struct sll_node {
	struct sll_node *next;
} SLL_NODE;

#define SLL_LIST SLL_NODE

void list_init(SLL_LIST *list);

void list_insert_head(SLL_LIST *list, SLL_NODE *node);

void list_insert_after(SLL_LIST *list, SLL_NODE *prev, SLL_NODE *node);

void list_delete_head(SLL_LIST *list);

void list_delete(SLL_LIST *list, SLL_NODE *node);

void list_delete2(SLL_LIST *list, SLL_NODE *node);

int list_get_num(SLL_LIST *list);

#endif
#if 1

#include <stdlib.h>
#include "sll4.h"

#if 0
/* singly linked list */
typedef struct sll_node {
	struct sll_node *next;
} SLL_LIST;

#define SLL_LIST SLL_NODE
#endif

/*
参数:SLL_LIST *list
返回值:void
作用:初始化链表
*/
void list_init(SLL_LIST *list)
{
	if (list == NULL) {
		return;  
	}

	list->next = NULL;
}

/*
参数:SLL_LIST *list, SLL_NODE *node
返回值:SLL_NODE *
作用:找到node节点的前驱
*/
SLL_NODE *list_find_prev(SLL_LIST *list, SLL_NODE *node)
{
	SLL_NODE *prev = NULL;

	if ((list == NULL) || (node == NULL)) {
		return NULL;
	}

	prev = list;
	while (prev->next != NULL) {
		if (prev->next == node) {
			break;
		}

		prev = prev->next;
	}

	return prev;
}

/*
参数:SLL_LIST *list, SLL_NODE *node
返回值:void
作用:在链表头部插入node节点
*/
void list_insert_head(SLL_LIST *list, SLL_NODE *node)
{
	if ((list == NULL) || (node == NULL)) {
		return;
	}

	node->next = list->next;
	list->next = node;
}

/*
参数:SLL_LIST *list, SLL_NODE *pos, SLL_NODE *node
返回值:void
作用:在pos节点后面插入node节点
*/
void list_insert_after(SLL_LIST *list, SLL_NODE *prev, SLL_NODE *node)
{
	if ((pos == NULL) || (node == NULL)) {
		return;
	}

	node->next = prev->next;
	prev->next = node;
}

/*
参数:SLL_LIST *list
返回值:void
作用:删除链表头节点
*/
void list_delete_head(SLL_LIST *list)
{
	SLL_NODE *head = NULL;

	if (list == NULL) {
		return;
	}

	head = list->next;
	if (head != NULL) {
		list->next = head->next;
		head->next = NULL;
	}
}

/*
参数:SLL_LIST *list, SLL_NODE *node
返回值:void
作用:删除node节点
*/
void list_delete(SLL_LIST *list, SLL_NODE *node) 
{
	SLL_NODE *prev = NULL;

	if ((list == NULL) || (node == NULL)) {
		return ;
	}

	prev = list;
	while (prev->next != NULL) {
		if (prev->next == node) {
			prev->next = node->next;
			node->next = NULL;
			break;
		}

		prev = prev->next;
	}
}

/*
参数:SLL_LIST *list, SLL_NODE *node
返回值:void
作用:删除node节点
*/
void list_delete2(SLL_LIST *list, SLL_NODE *node)
{
	SLL_NODE *prev = NULL;

	if ((list == NULL) || (node == NULL)) {
		return ;
	}

	prev = list_find_prev(list, node);
	if (prev != NULL) {
		prev->next = node->next;
		node->next = NULL;
	}
}

/*
参数:SLL_LIST *list
返回值:void
作用:初始化链表
*/
int list_get_num(SLL_LIST *list)
{
	int num = 0;
	SLL_NODE *iter = NULL;

	if (list == NULL) {
		return 0;
	}

	iter = list->next;
	while (iter != NULL) {
		num++;
		iter = iter->next;
	}

	return num;
}

#endif
#if 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "sll4.h"

typedef struct life {
	SLL_NODE node;
	int work;
	int study;
	int play;
} LIFE;

typedef struct all_life {
	SLL_LIST list;
} ALL_LIFE;


void slist_print(ALL_LIFE *all_life)
{
	SLL_NODE *iter = all_life->list.next;
	LIFE *pLIFE = NULL;
	int index = 0;

	while (iter != NULL) {
		pLIFE = (LIFE *)iter;
		printf("%2d: work: %d, study: %d, play: %d\n",
			++index, pLIFE->work, pLIFE->study, pLIFE->play);

		iter = iter->next;
	}

	printf("\n");
}


int main()
{
	int i = 0;
	int arr[] = { 123, 4, 3, 34, 35, 7, 8, 9, 5, 4, 2, 1 };
	int len = sizeof(arr) / sizeof(arr[0]);
	struct all_life real_life = { 0 };
	struct life *my_life = NULL;

	for (i = 0; i < len; i++) {
		my_life = (struct life *)malloc(sizeof(struct life));
		if (my_life == NULL) {
			printf("malloc error!\n");
			return 1;
		}

		my_life->node.next = NULL;
		my_life->work = arr[i];
		my_life->study = arr[i] + 1;
		my_life->play = arr[i] + 2;

		list_insert_head(&(real_life.list), &(my_life->node));
	}

	slist_print(&real_life);

	for (i = 0; i < len; i++) {
		my_life = (LIFE *)GET_LIST_HEAD(real_life.list);
		list_delete2(&(real_life.list), &(my_life->node));
		free(my_life);
		my_life = NULL;
		slist_print(&real_life);
	}

	getchar();

	return 0;
}

#endif

使用二级指针进行链表的删除操作,将各种情况归一化,可以简化代码,但理解起来有难度。(保存next的地址)


#ifndef _MY_LIST3_H
#define _MY_LIST3_H

typedef struct notify_node {
	struct notify_node *next;
	int key;
} NOTIFY_NODE;

typedef struct notify_list {
	struct notify_node *head;
} NOTIFY_LIST;

void ListInsert(NOTIFY_LIST *list, NOTIFY_NODE *node);

void ListDelete(NOTIFY_LIST *list, NOTIFY_NODE *node);

NOTIFY_NODE *ListFindNode(NOTIFY_LIST *list, int key);

void ListMerge(NOTIFY_LIST *list1, NOTIFY_LIST *list2, NOTIFY_LIST *list);

#endif 
#include <stdlib.h>
#include "sll3.h"


/*
参数:NOTIFY_LIST *list, NOTIFY_NODE *node
返回值:void
作用:插入node节点
*/
void ListInsert(NOTIFY_LIST *list, NOTIFY_NODE *node)
{
	NOTIFY_NODE **iter = NULL;

	if (list == NULL || node == NULL) {
		return;
	}

	iter = &(list->head);
	while ((*iter) != NULL) {
		if ((*iter)->key > node->key) {
			break;
		}

		iter = &((*iter)->next);
	}

	node->next = (*iter);
	(*iter) = node;
}

/*
参数:NOTIFY_LIST *list, NOTIFY_NODE *node
返回值:void
作用:删除node节点
*/
void ListDelete(NOTIFY_LIST *list, NOTIFY_NODE *node)
{
	NOTIFY_NODE **iter = NULL;

	if (list == NULL || node == NULL) {
		return;
	}

	iter = &(list->head);
	while ((*iter) != NULL) {
		if ((*iter) == node) {
			(*iter) = node->next;
			node->next = NULL;
			break;
		}

		iter = &((*iter)->next);
	}
}

/*
参数:NOTIFY_LIST *list, int key
返回值:NOTIFY_NODE *
作用:通过key查找节点
*/
NOTIFY_NODE *ListFindNode(NOTIFY_LIST *list, int key)
{
	NOTIFY_NODE *iter = list->head;

	while (iter != NULL) {
		if (iter->key == key) {
			break;
		}

		iter = iter->next;
	}

	return iter;
}

/*
参数:NOTIFY_LIST *list1, NOTIFY_LIST *list2, NOTIFY_LIST *list
返回值:void
作用:合并链表
*/
void ListMerge(NOTIFY_LIST *list1, NOTIFY_LIST *list2, NOTIFY_LIST *list)
{
	NOTIFY_NODE **iter = &(list->head);
	NOTIFY_NODE *iter1 = list1->head;
	NOTIFY_NODE *iter2 = list2->head;

	while (iter1 != NULL && iter2 != NULL) {
		if (iter1->key < iter2->key) {
			(*iter) = iter1;
			iter1 = iter1->next;
		} else {
			(*iter) = iter2;
			iter2 = iter2->next;
		}
		iter = &((*iter)->next);
	}

	if (iter1 != NULL) {
		(*iter) = iter1;
	}

	if (iter2 != NULL) {
		(*iter) = iter2;
	}
}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "sll3.h"


typedef struct life {
	NOTIFY_NODE node;
	int work;
	int study;
	int play;
} LIFT;

typedef struct all_life {
	NOTIFY_LIST list;
} ALL_LIFT;


void slist_print(ALL_LIFT *list)
{
	NOTIFY_NODE *iter = list->list.head;
	LIFT *plift = NULL;
	int index = 0;

	while (iter != NULL) {
		plift = (LIFT *)iter;
		printf("%2d: work: %d, study: %d, play: %d\n",
			++index, plift->work, plift->study, plift->play);

		iter = iter->next;
	}

	printf("\n");
}

LIFT *slist_find(ALL_LIFT *list, int key)
{
	NOTIFY_NODE *iter = NULL;

	iter = ListFindNode(&(list->list), key);

	return (LIFT *)iter;
}


int main()
{
	int i = 0;
	int arr[] = { 123, 4, 3, 34, 35, 7, 8, 9, 5, 4, 2, 1 };
	int len = sizeof(arr) / sizeof(arr[0]);
	struct all_life real_life = { 0 };
	struct life *my_life = NULL;

	for (i = 0; i < len; i++) {
		my_life = (struct life *)malloc(sizeof(struct life));
		if (my_life == NULL) {
			printf("malloc error!\n");
			return 1;
		}

		my_life->node.key = arr[i];
		my_life->node.next = NULL;
		my_life->work = arr[i];
		my_life->study = arr[i] + 1;
		my_life->play = arr[i] + 2;

		ListInsert(&(real_life.list), &(my_life->node));
	}

	slist_print(&real_life);

	for (i = 0; i < len; i++) {
		my_life = slist_find(&real_life, arr[i]);
		ListDelete(&(real_life.list), &(my_life->node));
		free(my_life);
		my_life = NULL;
		slist_print(&real_life);
	}

	getchar();

	return 0;
}

 

 

 

 

 

 

 

 



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值