数据结构--单链表C/C++

最近在学习数据结构,其中有介绍单链表跟单循环链表的,现在复习一下。首先要定义一下数据结构(节点),如下:

typedef int DataType; //方便后面修改数据类型,有点像C++/JAVA中的泛型
typedef struct Node 
{
	DataType data;
	struct Node *next;
}Node;

单链表: 

接下来是定义一个获取链表某个位置节点的函数,如下:
 

Node* getptr(Node* head, int pos)
{
	Node *p = head;
	if (p == NULL || pos == 0)
	{
		return head;
	}
	for (int i = 0; p && i < pos; i++)
	{
		p = p->next;
	}
	return p;
}

获取链表有几个节点,如下:

int getSize(Node* head)
{
	int size = 0;
	Node *p = head;
	while(p)
	{
		size++;
		p = p->next;
	}
	return size;
}

向链表中添加新的节点数据,如下:

bool insert(Node** head, int position, DataType d)
{
	if (position < 0 || position > getSize(*head))
	{
		return false;
	}

	Node *node = (Node*)malloc(sizeof(Node));
	node->data = d;
	node->next = NULL;
	if (position == 0)
	{
		node->next = *head;
		*head = node;
		return true;
	}
	Node *p = getptr(*head, position - 1);
	Node *r = p->next;
	node->next = r;
	p->next = node;
	return true;
}

这里head使用了指针的指针,使用指针的指针是因为调用处需要带回head的改变,即实参需要改变;形参head执行完函数insert后是会被释放掉的。来张内存分配图:

 

 将两个链表拼接到一起,如下:

void unionList(Node *a, Node *b)
{
	Node *p = a;
	while(p->next)
		p = p->next;
	p->next = b;
}

将链表数据打印出来,如下:
 

void print(DataType d)
{
	printf("%d\t", d);
}

void trave(Node *head, void(*fun)(DataType))
{
	Node *p = head;
	while(p)
	{
		fun(p->data);
		p = p->next;
	}
}

 删除某个位置的链表节点,如下:

bool erase(Node **head, int pos)
{
	if (pos < 0 || pos >= getSize(*head))
	{
		return false;
	}
	Node *p = *head;
	if (pos == 0)
	{
		*head = (*head)->next;
		free(p);
		p = NULL;
		return true;
	}
	p = getptr(*head, pos - 1);
	Node *q = p->next;
	p->next = q->next;
	free(q);
	q = NULL;
	return true;
}

将链表倒置,如下:

bool erase(Node **head, int pos)
{
	if (pos < 0 || pos >= getSize(*head))
	{
		return false;
	}
	Node *p = *head;
	if (pos == 0)
	{
		*head = (*head)->next;
		free(p);
		p = NULL;
		return true;
	}
	p = getptr(*head, pos - 1);
	Node *q = p->next;
	p->next = q->next;
	free(q);
	q = NULL;
	return true;
}

 删除链表,如果节点中的data开辟了内存,也需要释放,这个没有开辟内存,所以不需要释放,如下:

void deleteAll(Node **head)
{
	Node *tmp, *n, *h;
	if (head == NULL)
		return;
	h = *head;
	for (tmp = h->next; tmp != NULL; tmp = n)
	{
		n = tmp->next;
		free(tmp);		
	}
	free(h);
	*head = NULL;
}

 函数测试代码如下:

#include "SingleList.h"
#include <stdio.h>

int main()
{
	Node *head = NULL;
	insert(&head, 0, 9);	
	insert(&head, 0, 8);
	insert(&head, 0, 3);
	insert(&head, 0, 11);
	printf("init------------>\n");
	trave(head, print);
	int len = getSize(head);
	printf("\n getSize = %d\n", len);
	bool b = erase(&head, 2);
	if (b)
	{
		printf("erase--------->\n");
		trave(head, print);
	}
	printf("\n reverse------------->\n");
	reverse(&head);
	trave(head, print);
	
	printf("\n head2-------init-->\n");
	
	Node *head2 = NULL;
	insert(&head2, 0, 20);	
	insert(&head2, 0, 22);
	insert(&head2, 0, 14);
	insert(&head2, 0, 19);
	trave(head2, print);
	printf("\n unionList--------->\n");
	unionList(head, head2);
	trave(head, print);
	printf("\n deleteAll--------->\n");
	deleteAll(&head);
	trave(head, print);
	printf("\n----main end -----\n");
	
	return 0;
}


 编译运行结果如下:

 

 单循环链表:

获取链表长度,rear是尾指针,指向最后一个节点,如下:

int getSize(Node *rear)
{
	int size = 0;
	if (rear)
	{
		Node *p = rear->next;
		while (p != rear)
		{
			size++;
			p = p->next;
		}
		size++;
	}
	return size;
}

跟位置获取对应链表节点,如下:

Node *getptr(Node *rear, int pos)
{
	if (rear == NULL)
	{
		return rear;
	}
	if (pos >= getSize(rear))
	{
		return NULL;	
	}
	Node *p = rear->next;
	for(int i = 0; i < pos; i++)
	{
		p = p->next;
	}
	return p;
}

 向链表中添加节点,如下:
 

bool insert(Node **rear, int position, DataType d)
{
	if (position < 0 || position > getSize(*rear))
	{
		return false;
	}
	Node *node = (Node *)malloc(sizeof(Node));
	node->data = d;
	node->next = NULL;
	if (position == 0)
	{
		if (*rear == NULL)
		{
			node->next = node;
			*rear = node;
		}
		else
		{
			node->next = (*rear)->next;
			(*rear)->next = node;
		}
		return true;
	}	
	Node *p = getptr(*rear, position - 1);
	Node *r = p->next;
	node->next = r;
	p->next = node;
	if (*rear == p)
	{
		*rear = node;	
	}
	return true;
}

删除链表中某个节点,如下:

 

bool erase(Node **rear, int pos)
{
	if (*rear == NULL || pos < 0 || pos >= getSize(*rear))
	{
		return false;
	}
	Node *p = (*rear)->next;
	if (pos == 0)
	{
		(*rear)->next = p->next;
		free(p);
		p = NULL;
		return true;
	}

	p = getptr(*rear, pos - 1);
	Node *q = p->next;
	p->next = q->next;
	if (q == *rear)
	{
		*rear = p;
	}
	free(q);
	q = NULL;
	return true;
}

 链表数据打印,如下:

void print(DataType d)
{
	printf("%d\t", d);
}

void trave(Node *rear, void(*fun)(DataType))
{
	if (rear == NULL)
		return;
	Node *p = rear->next;
	while(p != rear)
	{
		fun(p->data);
		p = p->next;
	}
	fun(p->data);
}

测试代码如下:

#include "cycleList.h"

int main()
{
	Node *rear = NULL;
	insert(&rear, 0, 8);
	insert(&rear, 0, 3);
	insert(&rear, 0, 19);
	insert(&rear, 0, 6);
	printf("\n==============main init=============\n");
	trave(rear, print);
	printf("\n==============erase init=============\n");
	erase(&rear, 1);
	trave(rear, print);
	printf("\n==============main end=============\n");
	return 0;
}

测试结果如下:

 

代码参考:

单链表:https://github.com/gunder1129/android-tool/tree/master/dataStructure/singleList

单循环链表: https://github.com/gunder1129/android-tool/tree/master/dataStructure/cycleList

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值