单链表也是很朴素的数据结构,思想很简单。用next域存储下个节点。通常加一个头结点会很方便。
虽然不用移动大量元素,但是查找定位的时候必须顺着链表遍历,不能随机存储,时间复杂度还是O(n)。
优点是不需要来回分配存储空间,只需要按需存储,对于查询操作比较弱的需要,满足比较好。
代码也是很简单的,注释已经很清楚了。
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
using namespace std;
// 单链表的实现
typedef int ElemType;
typedef bool Status;
#define OK true;
#define FAIL false;
typedef struct LNode {
ElemType data;
struct LNode* next;
}LNode, *LinkList;
LinkList InitList() {
LinkList head = new LNode();
head->next = NULL;
head->data = 0; // 单链表头指针数据域存放链表长度
return head;
}
Status CreateList(LinkList head, ElemType* data, int size) {
LinkList pNode = head;
for(int i=0; i<size; i++) {
LinkList tmp = new LNode();
tmp->next = NULL;
tmp->data = data[i];
pNode->next = tmp;
head->data++;
pNode = pNode->next;
}
return OK;
}
// index不是下标,是第几个
Status GetElem(LinkList head, int i, ElemType &e) {
if(i<1 || i>head->data)
return FAIL;
LinkList pNode = head->next;
int count(1);
while(pNode) {
if(count==i)
break;
pNode = pNode->next;
count++;
}
e = pNode->data;
return OK;
}
// 其实就是遍历顺序表,效率低下,按值查找通常要先排序
LinkList LocateElem(LinkList head, ElemType x) {
LinkList pNode = head->next;
while(pNode) {
if(pNode->data == x)
return pNode;
pNode = pNode->next;
}
return NULL; // 没找到
}
Status ListInsert(LinkList head, int i, ElemType e) {
if(i<1 || i>head->data+1)
return FAIL;
LinkList pNode = head->next;
int count(1);
while (pNode) {
if (count == 1) {
LinkList pNewNode = new LNode();
pNewNode->data=e;
pNewNode->next = pNode->next;
pNode->next = pNewNode;
head->data++;
break;
}
pNode = pNode->next;
}
return OK;
}
Status ListDelete(LinkList head, int i, ElemType &e) {
if(i<1 || i>head->data)
return FAIL;
LinkList pNode = head->next;
LinkList prior = head;
int count(1);
while (pNode) {
if(count==i)
break;
else
prior = pNode;
pNode = pNode->next;
count++;
}
e = pNode->data;
printf("%d %d %d\n", e, count, i);
prior->next = pNode->next;
delete pNode;
head->data--;
return OK;
}
void print(LinkList head) {
cout<<"输出顺序表"<<endl;
printf("Sqlist size: %d\n", head->data);
LinkList pNode = head->next;
while(pNode) {
printf("%d\t", pNode->data);
pNode = pNode->next;
}
cout<<endl;
}
void DestroyList(LinkList head) {
LinkList pNode = head->next;
while (pNode) {
LinkList tmp = pNode;
pNode = pNode->next;
delete tmp;
}
head->next = NULL;
head->data = 0;
}
// 由于用头结点的data存储长度信息,直接返回,如果没有的话,那需要遍历查找
int getLength(LinkList head) {
if(head)
return head->data;
else
return 0;
}
int main() {
ElemType testCase[] = {
6501,6828,6963,7036,7422,7674,8146,8468,8704,8717,9170,9359,9719,9895,9896,9913,9962,154,293,334,492,1323,
1479,1539,1727,1870,1943,2383,2392,2996,3282,3812,3903,4465,4605,4665,4772,4828,5142,5437,5448,5668,5706,
5725,6300,6335
};
int size = sizeof(testCase) / sizeof(ElemType);
LinkList head = InitList();
print(head);
CreateList(head, testCase, size);
print(head);
printf("\nget element by index\n");
for(int i=1; i<=size; i++) {
int e;
GetElem(head, i, e); // i是第几个,不是数组下标
printf("%d: %d\t", i, e);
}
printf("\n\nget location of element\n");
printf("index: %d\n", LocateElem(head, 12)!=NULL?LocateElem(head, 12)->data:-1);
printf("index: %d\n", LocateElem(head, 9913)!=NULL?LocateElem(head, 9913)->data:-1);
printf("\n\ninsert element\n");
ListInsert(head, 5, 10);
print(head);
for(int i=0; i<100; i++)
ListInsert(head, 5, i);
print(head);
printf("\n\n删除性测试\n");
ElemType e;
for(int i=1; i<=5; i++) {
ListDelete(head, i, e); // i是第几个,不是数组下标
printf("e: %d\n", e);
print(head);
}
DestroyList(head);
return 0;
}