单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
在本文中单链表都使用了头节点来简化操作,头指针head指向头结点。链表由头指针唯一确定,单链表可以用头指针的名字来命名。
#include <iostream>
using namespace std;
#define ElemType int
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
void PrintList(LinkList L);
/**
* 按位插入
* @param L
* @param i 插入的位置
* @param e 插入的值
* @return
*/
bool ListInsert(LinkList &L, int i, ElemType e);
bool InsertNextNode(LNode *p, ElemType e);
/**
* 实际上还是后插结点,只不过将新的结点的值与后插的值互换,达到逻辑上的前插
* @param p
* @param e
* @return
*/
bool InsertBeforeNode(LNode *p, ElemType e);
/**
* 头插法建立链表
* @param L
* @return
*/
LinkList Insert_Head(LinkList &L);
/**
* 尾插法建立,顺序相同
* @param L
* @return
*/
LinkList Insert_Tail(LinkList &L);
/**
* 按位删除,将删除后的数据返回
* @param L
* @param i
* @param e
* @return
*/
bool ListDelete(LinkList &L, int i, ElemType &e);
/**
* 删除指定节点
* @param p
* @return
*/
bool DeleteNode(LNode *p);
LNode* GetElem(LinkList L, int i);
int main() {
LinkList L;
Insert_Tail(L);
ListInsert(L, 2, 421);
PrintList(L);
cout << GetElem(L, 3)->data << endl;
return 0;
}
bool ListInsert(LinkList &L, int i, ElemType e) {
if (i < 1)
return false;
LNode *p = L;
int j = 0;
//遍历到前一个节点即可
while (p != nullptr && j < i - 1) {
p = p->next;
j++;
}
if (p == nullptr)
return false;
LNode *lNode = (LNode *) malloc(sizeof(LNode));
lNode->data = e;
//插入代码,注意顺序不能写错!!!,否则新结点不能指向下一个结点
lNode->next = p->next;
p->next = lNode;
return true;
}
bool InsertNextNode(LNode *p, ElemType e) {
//判断传入指针是否为空指针
if (p == nullptr)
return false;
LNode *lNode = (LNode *) malloc(sizeof(LNode));
//判断内存分配是否成功
if (lNode == nullptr)
return false;
lNode->data = e;
lNode->next = p->next;
p->next = lNode;
return true;
}
bool InsertBeforeNode(LNode *p, ElemType e) {
if (p == nullptr)
return false;
LNode *lNode = (LNode *) malloc(sizeof(LNode));
if (lNode == nullptr)
return false;
lNode->next = p->next;
p->next = lNode;
lNode->data = p->data;
p->data = e;
return true;
}
LinkList Insert_Head(LinkList &L) {
LNode *lNode;
ElemType e;
L = (LinkList) malloc(sizeof (LNode));
L->next = nullptr;
printf("请输入元素,输入999结束");
scanf("%d", &e);
while (e != 999) {
lNode = (LNode *) malloc(sizeof (LNode *));
lNode->data = e;
lNode->next = L->next;
L->next = lNode;
scanf("%d", &e);
}
return L;
}
LinkList Insert_Tail(LinkList &L) {
ElemType e;
LNode *lNode;
LNode *tail;
L = (LinkList) malloc(sizeof (LNode));
tail = L;
printf("请输入元素,输入999结束");
scanf("%d", &e);
while (e != 999) {
lNode = (LNode *) malloc(sizeof (LNode));
lNode->data = e;
//将新的指针置于尾指针后,并在插入完成后置为尾指针
tail->next = lNode;
tail = lNode;
scanf("%d", &e);
}
//将尾指针置为空
tail->next = nullptr;
return L;
}
void PrintList(LinkList L) {
LNode *p = L->next;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
bool ListDelete(LinkList &L, int i, ElemType &e) {
if (i < 1)
return false;
LNode *p = L;
int j=0;
while (p!= nullptr && j<i-1) {
p = p->next;
j++;
}
if (p == nullptr || p->next == nullptr)
return false;
LNode *delNode = p->next;
e = delNode->data;
//最好别写p->next = p->next->next 这样不好释放内存
p->next = delNode->next;
//释放内存
free(delNode);
return true;
}
bool DeleteNode(LNode *p) {
if (p == nullptr)
return false;
LNode *delNode = p->next;
p->data = delNode->data;
p->next = delNode->next;
free(delNode);
return true;
}
LNode* GetElem(LinkList L, int i) {
if (i < 1)
return nullptr;
int j = 1;
LNode *p = L->next;
while (p!= nullptr && j < i) {
p = p->next;
j++;
}
return p;
}
//反转链表
LinkList reverseList(LinkList L) {
LNode *curr = L->next;
LNode *pre = nullptr;
while (curr != nullptr) {
LNode *temp = curr->next;
curr->next = pre;
pre = curr;
curr = temp;
}
LNode *head = nullptr;
//在此处加一个头节点,方便我们去调用PrintList函数
head->next = pre;
return head;
}