【学习笔记】链表(C/C++)

链表总述

不同于连续空间内存在的数组,数据在链表中的地址是离散的。插入/删除快,但存储密度小。
链表分有无头结点,是否循环,以及可否双向遍历。
以典型的非循有头单链表为例:

链表结构
插入操作:

单链表插入
删除结点操作:
单链表删结点
链表逆置:
单链表の头疼の逆置

代码

完整实现代码(C++):

#include <iostream>

using namespace std;

// 链表分8类,是否循环,是否双向,是否有头

// 结点
class Node
{
public:
	int value;
	Node* next;
	Node(int v, Node* n) : value(v), next(n) {}
};

template<typename T>
void swapElem(T& a, T& b)
{
	T t = a;
	a = b;
	b = t;
}

// 非循环有头单链表
class LinkList
{
public:
	Node* head = new Node(0, NULL); // 头
	int length = 0;

	LinkList(int* a, int len) // 有参构造
	{
		for (int i = 0; i < len; ++i)
		{
			addBack(a[i]);
		}
	}

	/*--------------------------   插入   ----------------------------*/

	void addBack(int value) // 尾插
	{
		Node* newElement = new Node(value, NULL);
		tail()->next = newElement;
		++length;
	}

	void addFront(int value) // 头插
	{
		Node* newFirstElem = new Node(value, head->next);
		head->next = newFirstElem;
		++length;
	}

	void add(int idx, int value) // 任意位置插入
	{
		if (idx > length - 1) throw "Linklist is not so long.";
		if (idx == 0)
		{
			addFront(value);
			return;
		}
		Node* former = ptrOf(idx - 1);
		Node* newElement = new Node(value, former->next);
		former->next = newElement;
		++length;
	}

	/*--------------------------   删改   ----------------------------*/

	void modify(int idx, int newv) // 修改
	{
		ptrOf(idx)->value = newv;
	}

	void popFront() // 头删
	{
		if (empty()) throw "Linklist is empty.";
		Node* toDel = head->next;
		head->next = toDel->next;
		delete toDel;
		toDel = NULL;
		--length;
	}

	void popBack() // 尾删
	{
		if (empty()) throw "Linklist is empty.";
		if (length == 1) { popFront(); return; }
		Node* Lsub2 = ptrOf(length - 2);
		delete Lsub2->next;
		Lsub2->next = NULL;
		--length;
	}

	void pop(int idx) // 任意位置删
	{
		if (idx == 0) { popFront(); return; }
		if (idx == length - 1) { popBack(); return; }
		Node* former = ptrOf(idx - 1);
		Node* toDel = former->next;
		Node* latter = toDel->next;
		delete toDel;
		toDel = NULL;
		former->next = latter;
		--length;
	}

	/*--------------------------   查   ----------------------------*/

	bool empty() // 判断是否为空
	{
		return head->next == NULL;
	}

	Node* tail() // 返回指向末元素的指针
	{
		if (empty()) return NULL;
		Node* nextptr = head->next;
		while (nextptr->next) nextptr = nextptr->next;
		return nextptr;
	}

	Node* ptrOf(int idx) // 根据序号索引结点位置
	{
		if (empty()) throw "Linklist is empty!";
		if (idx + 1 > length) throw "Linklist is not so long.";
		Node* nptr = head->next;
		for (int i = 0; i < idx; ++i)
		{
			nptr = nptr->next;
		}
		return nptr;
	}

	int valueOf(int idx) // 根据序号索引结点数据
	{
		return ptrOf(idx)->value;
	}

	int operator[](int idx)
	{
		return ptrOf(idx)->value;
	}

	int front()
	{
		if (empty()) throw "Linklist is empty.";
		return head->next->value;
	}

	int back()
	{
		if (empty()) throw "Linklist is empty.";
		return tail()->value;
	}

	/*--------------------------   调整顺序   ----------------------------*/

	void reverse() // 逆置
	{
		Node* pre = NULL;
		Node* temp = head->next;
		Node* nextptr = temp;
		while (temp)
		{
			nextptr = nextptr->next;
			temp->next = pre;
			pre = temp;
			temp = nextptr;
		}
		head->next = pre;
	}

	void bubble() // 排序,采用冒泡,只交换数据域
	{
		if (length < 2) return;
		for (int i = 0; i < length; ++i)
		{
			for (Node* i = head->next; i->next; i = i->next)
			{
				if (i->value > i->next->value)
				swapElem(i->value, i->next->value);
			}
		}
	}

	void Bubble() // 冒泡,但是重新组织结点关系
	{
		if (length < 2) return;
		for (int end = length - 1; end > 0; --end)
		{
			Node* pre = head;
			Node* temp = head->next;
			Node* nextptr = temp;
			while (nextptr->next)
			{
				nextptr = nextptr->next;
				/*-----------*/
				if (temp->value > nextptr->value)
				{
					temp->next = nextptr->next;
					nextptr->next = temp;
					pre->next = nextptr;
					swapElem(temp, nextptr);
				}
				/*-----------*/
				pre = temp;
				temp = nextptr;
			}
		}
	}
};

ostream& operator<<(ostream& cout, LinkList& l)
{
	Node* nptr = l.head->next;
	while (nptr) // 遍历输出
	{
		cout << nptr->value << " ";
		nptr = nptr->next;
	}
	return cout;
}

int main()
{
	int arr[] = { 1, 1, 4, 5, 1, 4 };
	LinkList t(arr, sizeof(arr)/sizeof(arr[0]));

	cout << t << endl;
	t.Bubble();
	cout << t << endl;
	return 0;
}

更让人头疼的,C语言描述:

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

void swap(int* a, int* b)
{
	int t = *a;
	*a = *b;
	*b = t;
}

typedef struct LinkNode
{
	int value;
	struct LinkNode* next;
} Node ;

// 非循环有头单链表
typedef struct LinkList
{
	Node *head;
	int length;
} Link ;


/*-----------------------------------------------*/
// 增
int addBack(Link* ll, int value);
int addFront(Link* ll, int value);
int add(Link* ll, int idx, int value);
// 删改
void modify(Link* ll, int idx, int newv);
int popFront(Link* ll);
int popBack(Link* ll);
int pop(Link* ll, int idx);
// 查
int empty(Link* ll);
Node* tail(Link* ll);
Node* ptrOf(Link* ll, int idx);
int front(Link* ll);
int back(Link* ll);
// 调
void reverse(Link* ll);
void bubble(Link* ll);
int Bubble(Link* ll);
/*-----------------------------------------------*/


int linkInit(Link* ll)
{
	ll->head = (Node*)malloc(sizeof(Node));
	if (ll->head) ll->head->next = 0;
	else return 0;
	ll->head->next = NULL;
	ll->length = 0;
	return 1;
}

void cpArray(Link* ll, int* a, int len)
{
	for (int i = 0; i < len; ++i)
	{
		addBack(ll, a[i]);
	}
}

int addBack(Link* ll, int value)
{
	Node* newElement = (Node*)malloc(sizeof(Node));
	if (newElement) newElement->next = NULL;
	else return 0;
	newElement->value = value;
	tail(ll)->next = newElement;
	++ll->length;
	return 1;
}

int addFront(Link* ll, int value)
{
	Node* newElement = (Node*)malloc(sizeof(Node));
	if (newElement) newElement->value = value;
	else return 0;
	newElement->next = ll->head->next;
	ll->head->next = newElement;
	return 1;
}

int add(Link* ll, int idx, int value)
{
	if (idx > ll->length - 1) return 0;
	if (idx == 0)
	{
		addFront(ll, value);
		return 1;
	}
	Node* former = ptrOf(ll, idx - 1);
	Node* newElement = (Node*)malloc(sizeof(Node));
	if (newElement) newElement->next = former->next;
	else return 0;
	newElement->value = value;
	former->next = newElement;
	++ll->length;
	return 1;
}

void modify(Link* ll, int idx, int newv)
{
	ptrOf(ll, idx)->value = newv;
}

int popFront(Link* ll)
{
	if (empty(ll)) return 0;
	Node* toDel = ll->head->next;
	ll->head->next = toDel->next;
	free(toDel);
	toDel = NULL;
	--ll->length;
	return 1;
}

int popBack(Link* ll)
{
	if (empty(ll)) return 0;
	if (ll->length == 1)
	{
		popFront(ll);
		return 1;
	}
	Node* Lsub2 = ptrOf(ll, ll->length - 2);
	free(Lsub2->next);
	Lsub2->next = NULL;
	--ll->length;
	return 1;
}

int pop(Link* ll, int idx)
{
	if (idx == 0)
	{
		popFront(ll);
		return 1;
	}
	if (idx == ll->length - 1)
	{
		popBack(ll);
		return 1;
	}
	Node* former = ptrOf(ll, idx - 1);
	Node* toDel = former->next;
	Node* latter = toDel->next;
	free(toDel);
	toDel = NULL;
	former->next = latter;
	--ll->length;
	return 1;
}

int empty(Link* ll)
{
	return ll->head->next == NULL;
}

Node* tail(Link* ll)
{
	if (empty(ll)) return NULL;
	Node* nextptr = ll->head->next;
	while (nextptr->next) nextptr = nextptr->next;
	return nextptr;
}

Node* ptrOf(Link* ll, int idx)
{
	if (empty(ll)) return NULL;
	if (idx + 1 > ll->length) return NULL;
	Node* nptr = ll->head->next;
	for (int i = 0; i < idx; ++i)
	{
		nptr = nptr->next;
	}
	return nptr;
}

int valueOf(Link* ll, int idx)
{
	return ptrOf(ll, idx)->value;
}

int front(Link* ll)
{
	return ll->head->value;
}

int back(Link* ll)
{
	return tail(ll)->value;
}

int reserve(Link* ll)
{
	if (empty(ll)) return 0;
	Node* pre = NULL;
	Node* temp = ll->head->next;
	Node* nextptr = temp;
	while (temp)
	{
		nextptr = nextptr->next;
		temp->next = pre;
		pre = temp;
		temp = nextptr;
	}
	ll->head->next = pre;
	return 1;
}

void bubble(Link* ll) // 排序,采用冒泡,只交换数据域
{
	if (ll->length < 2) return;
	for (int i = 0; i < ll->length; ++i)
	{
		for (Node* i = ll->head->next; i->next; i = i->next)
		{
			if (i->value > i->next->value)
				swap(&(i->value), &(i->next->value));
		}
	}
}

int Bubble(Link* ll) // 冒泡,但是重新组织结点关系
{
	if (ll->length < 1) return 0;
	if (ll->length < 2) return 1;
	for (int end = ll->length - 1; end > 0; --end)
	{
		Node* pre = ll->head;
		Node* temp = ll->head->next;
		Node* nextptr = temp;
		while (nextptr->next)
		{
			nextptr = nextptr->next;
			/*-----------*/
			if (temp->value > nextptr->value)
			{
				temp->next = nextptr->next;
				nextptr->next = temp;
				pre->next = nextptr;
				//swapElem(temp, nextptr);
				Node* p = temp;
				temp = nextptr;
				nextptr = p;
			}
			/*-----------*/
			pre = temp;
			temp = nextptr;
		}
	}
	return 1;
}

int main()
{
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值