- 链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中指针的连接次序实现的。
- 在8中链表中,常用的有两种:无头单向不循环链表和带头循环双向链表。
- 首先,无头单项不循环链表的结构简单,但是一般不用来存储数据,实际中更多的是作为其他数据结构的子结构,比如:哈希桶、图的邻接表等;
- 下面是其增删查改等操作的代码实现:
typedef int SLDataType;
/结点(数据和指向下一个结点的指针,其类型为结点指针)
typedef struct SListNode{
SLDataType _data;
struct SListNode* _next;
}SListNode;
/单链表(链表的起点:不是头结点,头结点不占空间)
typedef struct SList{
SListNode* _head;
}SList;
void SListInit(SList* plist){
assert(plist);
plist->_head = NULL;
}
/当链表的起点存在时就要开始删除(要记录每次删除结点的下一个结点)
void SListDestory(SList* plist){
assert(plist);
while (plist->_head){
SListNode* tNode = plist->_head->_next;
free(plist->_head);
plist->_head = tNode;
}
}
SListNode* BuySListNode(SLDataType x){
SListNode* newNode = (SListNode*)malloc(sizeof(SListNode));
assert(newNode);
newNode->_data = x;
newNode->_next = NULL;
return newNode;
}
/链表头插(如果当前链表不为空,就把新结点当做链表的起点,
/原链表的起点就变成了链表的第二个结点)
void SListPushFront(SList* plist, SLDataType x){
assert(plist);
SListNode* newNode = BuySListNode(x);
assert(newNode);
if (plist->_head == NULL){
plist->_head = newNode;
return;
}
else{
newNode->_next = plist->_head;
plist->_head = newNode;
}
}
void SListPopFront(SList* plist){
assert(plist);
SListNode* tNode = plist->_head->_next;
free(plist->_head);
plist->_head = tNode;
}
void SListPushBack(SList* plist,SLDataType x){
assert(plist);
SListNode* newNode = BuySListNode(x);
assert(newNode);
if (plist->_head == NULL){
plist->_head = newNode;
}
else{
SListNode* tail = plist->_head;
while (tail->_next){
tail = tail->_next;
}
tail->_next = newNode;
}
}
/尾删:有一个结点;
/有多个结点:要记录倒数第二个结点的位置
void SListPopBack(SList* plist){
assert(plist->_head);
SListNode* tail = plist->_head;
if (tail->_next == NULL){
free(tail);
plist->_head = NULL;
}
while (tail->_next->_next!=NULL){
tail = tail->_next;
}
free(tail->_next);
tail->_next = NULL;
}
SListNode* SListFind(SList* plist, SLDataType x){
assert(plist);
SListNode* tNode = plist->_head;
while (tNode != NULL){
if (tNode->_data != x){
tNode = tNode->_next;
}
else{
return tNode;
}
}
return -1;
}
/在pos的后面插入结点(pos位置不存在;pos在头上;pos在后边)
void SListInsertAfter(SList*plist,SListNode* pos, SLDataType x){
assert(plist);
SListNode* newNode = BuySListNode(x);
assert(newNode);
if (pos == -1){
return - 1;
}
else if (pos == plist->_head){
SListPushFront(plist,x);
}
else{
SListNode* tNode = plist->_head->_next;
while (tNode != pos){
tNode = tNode->_next;
}
tNode = pos->_next;
pos->_next = newNode;
newNode->_next = tNode;
}
}
/在pos的后面删除结点
void SListEraseAfter(SList*plist, SListNode* pos){
assert(plist);
if (pos == -1){
return -1;
}
else if (pos == plist->_head){
SListPopFront(plist);
}
else{
SListNode* tNode = plist->_head->_next;
while (tNode != pos){
tNode = tNode->_next;
}
SListNode* cur = tNode->_next;
SListNode* tail = tNode->_next->_next;
free(cur);
tNode->_next = tail;
}
}
/删除链表中的值为X的元素
void SListRemove(SList* plist, SLDataType x){
assert(plist);
SListNode* bNode = plist->_head;
if (bNode->_data == x){
SListNode* cur = bNode;
free(bNode);
cur->_next = plist->_head;
return;
}
else{
SListNode* tNode = plist->_head->_next;
while (tNode->_data != x){
bNode = bNode->_next;
tNode = tNode->_next;
}
SListNode* eNode = tNode->_next;
free(tNode);
bNode->_next = eNode;
}
}
/打印的时候,不能直接用plist->_head直接遍历,会改变头指针的位置。
void SListPrint(SList* plist){
assert(plist);
SListNode* head = plist->_head;
while (head->_next){
printf("%d->", head->_data);
head = head->_next;
}
printf("%d\n", head->_data);
}