C -- linked_list

链表(Linked List

  1. 定义结点类型,链表的基本单元:
typedef struct _node
{
	int value;
	struct _node * next;
}Node;
  1. 定义列表类型,存放链表头结点指针和尾结点指针,表示一个链表类型:
typedef struct _list
{
	Node * head;
	Node * tail;
}List;
  1. 声明一个结点基本单元并初始化
Node * p = (Node *) malloc (sizeof(Node));	
p->value = number;		
p->next = null;		
  1. 声明一个链表并初始化头尾指针
List list;
list.head = list.tail = NULL;
  1. 将新结点链接到list(Linked_list)上
//如果此时链表头为空,即开始添加刚申请到并初始化完成的第一个结点
if(list.head == NULL)		
	list.head = list.tail = p;
//否则则代表链表中已存在结点,将先前tail->next指向新申请到的p,完成链接新结点
else
{
	list.tail->next = p;
	list.tail = p;
}

通过以上五个步骤便已经完成了创建链表(linked_list)

关于链表的其他操作(查找、删除、清除

  1. 如何查找链表中相应元素,即如何遍历
Node * p;
for(p = list.head;p;p = p->next)
{
	if(p->value == number)
	{
		printf("Found!\n");
		break;
	}
}
  1. 删除链表指定元素,查找到删除当前位置,让前一个链接到后一个结点,注意删除头结点情况
Node *p,*q;
for(q = NULL,p = list.head;p;q = p,p = p->next)
	if(number == p->value)
		if(q == NULL)
		{
			list.head = p->next;
			break;
		}
		else
		{
			q->next = p->next;
			free(p);
			break;
		}
  1. 清除整个链表
Node *p,*q;
for(p = list.head;p;p = q)
{
	q = p->next;
	free(p);
}

以上是关于链表的常见操作(查找、删除、清除)的方法;

重点:关于封装的方法

需要注意的三点:

  1. 函数基于已定义的结点、链表类型
  2. 函数的接口采用指向链表的指针,便于修改链表
  3. 此处仅演示创建链表类型,传递链表指针处理的方法

优点:基于我们自己定义的List类型我们可以创建一系列的链表,并用各种函数处理单个链表,相当于有了一个链表的完整体系。

  1. 定义结点以及链表类型
//定义结点,链表的基本单元
typedef struct _node
{
	int value;
	struct _node * next;
}Node;

//定义链表类型,存放链表头结点指针和尾结点指针
typedef struct _list
{
	Node * head;
	Node * tail;
}List;

//声明一个链表
List list;
  1. 添加新结点的函数.
    函数原型: void add_to_list(List * ls, int num);
void add_to_list(List * ls, int num)
{
	Node * p = (Node *) malloc (sizeof(Node));	
	p->value = num;		
	p->next = null;		

	if(ls->head == NULL)
		ls->head = ls->tail = p;
	else
	{
		ls->tail->next = p;
		ls->tail = p;
	}
}
  1. 查找元素的函数.
    函数原型: void find_in_list(List * ls, int num);
void find_in_list(List * ls, int num)
{
	Node * p;
	bool isfound = false;

	for(p = ls->head;p;p = p->next)
		if(p->value == num)
		{
			isfound = true;
			break;
		}
	if(isfound)
		printf("Found!\n");
	else
		printf("Not Found!\n");
}
  1. 删除指定元素的函数
    函数原型: void del_a_num(List * ls, int num);
void del_a_num(List * ls, int num)
{
	Node *p, *q;
	for(q = NULL,p = ls->head;p;q=p, p = p->next)
		if(num == p->value)
		{
			if(q == NULL)
			{
				ls->head = p->next;
				break;
			}else
			{
				q->next = p->next;
				free(p);
				break;
			}
		}
}
  1. 清除整个链表的函数
    函数原型: void del_linked_list(List * ls);
void del_linked_list(List * ls)
{
	Node *p,*q;
	for(p = ls->head;p;p = q)
	{
		q = p->next;
		free(p);
	}
}

建立ADT并实现接口练习

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

//假设我们要做一个存放int类型值的一个链表,并开发建立接口

/* 第一步,建立抽象数据类型(ADT)	*/
//定义结点类型
typedef struct _node
{
	int value;
	struct _node * next;
}Node;
//定义链表类型,最终抽象出的ADT
typedef struct _list
{
	Node * head;
	Node * tail;
}List;

/* 第二步,抽象接口				*/
void add(List * ls, int val);//添加一个新项	
bool is_empty(const List * ls);//确定链表是否为空
bool is_full(const List * ls);//确定链表是否已满,遍历检查
int count(const List * ls);//确定链表项数
void show(const List * ls);//访问链表每一项,显示
void insert(List * ls, int index, int val);//链表中任意位置插入一个项
void remove(List * ls, int val);//移除链表中的一个项
bool found(const List * ls, int val);//在链表中检索一个项(不改变链表)
void change(List * ls, int index, int val);//用另一个项替换链表中的一个项
int research(const List * ls, int val);//链表中搜索一个项目,返回位置,-1表示未找到
void clear(List * ls);//清空整个链表

/* 第三步,实现接口		*/	
void add(List * ls, int val)
{
	Node * p = (Node *) malloc (sizeof(Node));
	p->value = val;
	p->next = NULL;

	//第一个结点
	if(ls->head == NULL)
		ls->head = ls->tail = p;
	else 		//后续结点
	{
		ls->tail->next = p;
		ls->tail = p;
	}
}

bool is_empty(const List * ls)
{
	bool ret = false;

	if(ls->head == NULL && ls->tail == NULL)
		ret = true;

	return ret;
}

bool is_full(const List * ls)
{
	bool ret = true;

	Node * p;
	for(p = ls->head;p;p = p->next)
		if(&(p->value) == NULL)
		{
			ret = false;
			break;
		}

		return ret;
}

int count(const List * ls)
{
	int cnt = 0;

	Node * p;
	for(p = ls->head;p;p = p->next)
		cnt++;

	return cnt;
}

void show(const List * ls)
{
	Node * p;
	for(p = ls->head;p;p = p->next)
		printf("%d ",p->value);
	putchar('\n');
}

void insert(List * ls, int index, int val)
{
	int i = 0;
	Node * new = (Node *) malloc (sizeof(Node));
	new->value = val;

	Node * p, * q;
	for(q = NULL, p = ls->head;p;q = p, p = p->next,i++)
	{
		//插在第一个
		if(index == 0)
		{
			new->next = ls->head;
			ls->head = new;
			break;
		//插在最后一个
		}else if (index == count(ls)) {
			new->next = NULL;
			ls->tail->next = new;
			ls->tail = new;
			break;
		//插在中间
		}else if (index == i) {
			q->next = new;
			new->next = p;
			break;
		}
	}
}

void remove(List * ls, int val)
{
	Node *p, *q;
	for(q = NULL, p = ls->head;p;q = p, p = p->next)
		if(p->value == val)
		{
			//删除的是第一个
			if(q == NULL)
			{
				ls->head = p->next;
				free(p);
				break;
			}else
			{
				q->next = p->next;
				free(p);
				break;
			}
		}
}

bool found(const List * ls, int val)
{
	bool ret = false;

	Node * p;
	for(p = ls->head;p;p = p->next)
		if(p->value == val)
			ret = true;
	
	return ret;
}

void change(List * ls, int index, int val)
{
	int i = 0;
	Node * p;
	for(p = ls->head;p;p = p->next, i++)
		if(i == index)
		{
			p->value = val;
			break;
		}
}

int research(const List * ls, int val)
{
	int ret = -1;
	int index = 0;
	Node * p;
	for(p = ls->head;p;p = p->next, index++)
		if(p->value == val)
		{
			ret = index;
			break;
		}

		return ret;
}

void clear(List * ls)
{
	Node *q, *p;
	for(p = ls->head;p;p = q)
	{
		q = p->next;
		free(p);
	}
}

驱动测试以上接口

测试接口


2019.12.7
修炼之路(一)
未完待续
归期不定
by lx

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
请参考我给出的代码框架,实现对EMPLOYEE结构体为数据的双向链表的排序算法,要求按照按employeeId升序排列 typedef struct linkNode { void* data; //使用空指针使得NODE适配多种数据结构 struct linkNode* preNode; struct linkNode* nextNode; }LINKED_NODE; /*Define the struct of double linked list.*/ typedef struct { LINKED_NODE* head; LINKED_NODE* tail; size_t size; }DOUBLE_LINK_LIST; typedef struct { int employeeId; char name[20]; char ipAddress[30]; char seatNumber[20]; char group[10]; } EMPLOYEE; DOUBLE_LINK_LIST* createDoubleLinkedList() { DOUBLE_LINK_LIST* newList = (DOUBLE_LINK_LIST*)malloc(sizeof(DOUBLE_LINK_LIST)); newList->head = NULL; newList->tail = NULL; newList->size = 0; return newList; } void destroyDoubleLinkedList(DOUBLE_LINK_LIST* list) {} /*Add a new node before the head.*/ void insertHead(DOUBLE_LINK_LIST* list, void* data) // void执政适配其他data类型? {} /*Add a new node after tail.*/ void insertTail(DOUBLE_LINK_LIST* list, void* data) // 如何适配其他data类型? {} /*Insert a new node.*/ void insertNode(DOUBLE_LINK_LIST* list, void* data,int index) // 如何适配其他data类型? {} void deleteHead(DOUBLE_LINK_LIST* list) {} void deleteTail(DOUBLE_LINK_LIST* list) {} void deleteNode(DOUBLE_LINK_LIST* list, int index) {} LINKED_NODE* getNode(DOUBLE_LINK_LIST* list, int index) {} /* 遍历链表,对每个节点执行指定操作*/ void traverseList(DOUBLE_LINK_LIST* list, void (*callback)(void*)) { LINKED_NODE* currentNode = list->head; while (currentNode != NULL) { callback(currentNode->data); currentNode = currentNode->nextNode; } } void printEmployee(void* data) {}
最新发布
07-25

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值