前言
- 在顺序表中,用一组地址连续的存储单元来存放线性表的结点,因此结点的逻辑顺序和物理顺序是一致的。
- 链表使用一组任意的存储单元来存放线性表的结点
单链表
1.简介
1.1:单链表特点
- 结点包括两个域:一个 数据域(用来存储结点的值) 和一个 指针域(用来指向该结点的直接后继结点的位置)
- 相比于顺序表的优点:对于空间的利用率 大大提高,实现了即用既申请.
- 相比于顺序表的缺点:在访问表中的某个结点(尾结点)时,需要遍历整个链表
2.单链表的实现
2.1:单链表结点结构的定义
typedef int SLDataType;
typedef struct SLNode{
SLDataType _value;
struct SLNode *next;
}SLNode;
2.2:指向链表的首结点的定义
typedef struct SList{
SLNode *first;
}SList;
2.3:单链表头结点的初始化
void SListInit(SList*list){
assert(list!=NULL);
list->first=NULL;
}
2.4:单链表的销毁
void SListDestory(SList *list){
assert(list!=NULL);
SLNode* cur=list->first;
SLNode *next=NULL;
while(cur!=NULL){
next=cur->next;
free(cur);
cur=next;
}
list->first=NULL;
}
- 动图演示
2.5:单链表的头插
void SListPushFront(SList *list,SLDataType value){
assert(list!=NULL);
SLNode* new_node=(SLNode*)malloc(sizeof(SLNode));
new_node->_value=value;
new_node->next=list->first;
list->first=new_node;
}
- 动图演示
2.6:单链表的尾插
void SListpushBack(SList *list, SLDataType value){
assert(list!=NULL);
SLNode* cur=list->first;
SLNode* new_node=(SLNode *)malloc(sizeof(SLNode));
while(cur->next!=NULL){
cur=cur->next;
}
new_node->_value=value;
new_node->next=cur->next;
cur->next=new_node;
}
- 动图演示
2.7:单链表结点的头删
void SListPopFront(SList *list){
assert(list!=NULL);
assert(list->first!=NULL);
SLNode *tmp=list->first;
list->first=list->first->next;
free(tmp);
}
- 动图演示
2.8:单链表结点的尾删
void SListPopBack(SList *list){
assert(list!=NULL);
assert(list->first!=NULL);
if(list->first->next==NULL){
SListPopFront(list);
return;
}
SLNode *cur=list->first;
while(cur->next->next!=NULL){
cur=cur->next;
}
free(cur->next);
cur->next=NULL;
}
- 动图演示
2.9:单链表中指定结点的查找
SLNode * SListFind(const SList *list, SLDataType value){
assert(list!=NULL);
assert(list->first!=NULL);
SLNode *cur=list->first;
while(cur!=NULL){
if(cur->_value==value)
return cur;
cur=cur->next;
}
return NULL;
}
2.10:单链表结点值的打印
void SListPrint(SList *list){
assert(list!=NULL);
SLNode *cur=list->first;
while(cur!=NULL){
printf("%d-->",cur->_value);
cur=cur->next;
}
printf("\n");
}
2.11:修改指定结点的值
void SlistNodeUpdate(SLNode *node, SLDataType value){
node->_value=value;
}
2.12:在指定的位置插入新的结点
void SListInsertAfter(SLNode *pos, SLDataType value){
assert(pos!=NULL);
SLNode *new_node=(SLNode*)malloc(sizeof(SLNode));
new_node->_value=value;
new_node->next=pos->next;
pos->next=new_node;
}
2.13:删除指定位置下一个结点
void SListEraseAfter(SLNode *pos){
assert(pos!=NULL);
SLNode* cur=pos->next;
pos->next=pos->next->next;
free(cur);
}
2.14:在指定位置前面插入新的结点
void SListInsertBefore(SList *list, SLNode *pos, SLDataType value){
assert(list!=NULL);
assert(pos!=NULL);
SLNode *new_node=(SLNode*)malloc(sizeof(SLNode));
SLNode* cur=list->first;
while(cur->next!=pos){
cur=cur->next;
}
new_node->_value=value;
new_node->next=pos;
cur->next=new_node;
}
单链表功能的整体实现
SList.h
#pragma once
#include<stdlib.h>
#include<stdio.h>
#include<assert.h>
typedef int SLDataType;
typedef struct SLNode{
SLDataType _value;
struct SLNode *next;
}SLNode;
typedef struct SList{
SLNode *first;
}SList;
void SListInit(SList*list);
void SListDestory(SList *list);
void SListPushFront(SList *list,SLDataType value);
void SListpushBack(SList *list, SLDataType value);
void SListPopFront(SList *list);
void SListPopBack(SList *list);
void SListPrint(SList *list);
SLNode * SListFind(const SList *list, SLDataType value);
void SlistNodeUpdate(SLNode *node, SLDataType value);
void SListInsertAfter(SLNode *pos, SLDataType value);
void SListEraseAfter(SLNode *pos);
void SListInsertBefore(SList *list, SLNode *pos, SLDataType value);
SList.c
#include"SList.h"
void SListInit(SList*list){
assert(list!=NULL);
list->first=NULL;
}
void SListDestory(SList *list){
assert(list!=NULL);
SLNode* cur=list->first;
SLNode *next=NULL;
while(cur!=NULL){
next=cur->next;
free(cur);
cur=next;
}
list->first=NULL;
}
void SListPushFront(SList *list,SLDataType value){
assert(list!=NULL);
SLNode* new_node=(SLNode*)malloc(sizeof(SLNode));
new_node->_value=value;
new_node->next=list->first;
list->first=new_node;
}
void SListpushBack(SList *list, SLDataType value){
assert(list!=NULL);
SLNode* cur=list->first;
SLNode* new_node=(SLNode *)malloc(sizeof(SLNode));
while(cur->next!=NULL){
cur=cur->next;
}
new_node->_value=value;
new_node->next=cur->next;
cur->next=new_node;
}
void SListPopFront(SList *list){
assert(list!=NULL);
assert(list->first!=NULL);
SLNode *tmp=list->first;
list->first=list->first->next;
free(tmp);
}
void SListPopBack(SList *list){
assert(list!=NULL);
assert(list->first!=NULL);
if(list->first->next==NULL){
SListPopFront(list);
return;
}
SLNode *cur=list->first;
while(cur->next->next!=NULL){
cur=cur->next;
}
free(cur->next);
cur->next=NULL;
}
void SListPrint(SList *list){
assert(list!=NULL);
SLNode *cur=list->first;
while(cur!=NULL){
printf("%d-->",cur->_value);
cur=cur->next;
}
printf("\n");
}
SLNode * SListFind(const SList *list, SLDataType value){
assert(list!=NULL);
assert(list->first!=NULL);
SLNode *cur=list->first;
while(cur!=NULL){
if(cur->_value==value)
return cur;
cur=cur->next;
}
return NULL;
}
void SlistNodeUpdate(SLNode *node, SLDataType value){
node->_value=value;
}
void SListInsertAfter(SLNode *pos, SLDataType value){
assert(pos!=NULL);
SLNode *new_node=(SLNode*)malloc(sizeof(SLNode));
new_node->_value=value;
new_node->next=pos->next;
pos->next=new_node;
}
void SListEraseAfter(SLNode *pos){
assert(pos!=NULL);
SLNode* cur=pos->next;
pos->next=pos->next->next;
free(cur);
}
void SListInsertBefore(SList *list, SLNode *pos, SLDataType value){
assert(list!=NULL);
assert(pos!=NULL);
SLNode *new_node=(SLNode*)malloc(sizeof(SLNode));
SLNode* cur=list->first;
while(cur->next!=pos){
cur=cur->next;
}
new_node->_value=value;
new_node->next=pos;
cur->next=new_node;
}
main.c
#include"SList.h"
void TestSLNode(){
SList slist;
SListInit(&slist);
SListPushFront(&slist,1);
SListPushFront(&slist,9);
SListPrint(&slist);
SListPushFront(&slist,8);
SListPrint(&slist);
SListPushFront(&slist,5);
SListPrint(&slist);
SListpushBack(&slist,4);
SListpushBack(&slist,3);
SListpushBack(&slist,2);
SListpushBack(&slist,100);
SListPrint(&slist);
SListPopFront(&slist);
SListPopBack(&slist);
SListPrint(&slist);
SListPopFront(&slist);
SListPrint(&slist);
SLNode* node=SListFind(&slist,3);
SListEraseAfter(node);
SListInsertAfter(node,520);
SListPrint(&slist);
SListEraseAfter(node);
SListInsertBefore(&slist,node,1314);
SListPrint(&slist);
}
int main()
{
TestSLNode();
return 0;
}