链表总述
不同于连续空间内存在的数组,数据在链表中的地址是离散的。插入/删除快,但存储密度小。
链表分有无头结点,是否循环,以及可否双向遍历。
以典型的非循有头单链表为例:
插入操作:
删除结点操作:
链表逆置:
代码
完整实现代码(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;
}