本次不给出头文件和main主函数了。可以参考之前的C语言数据结构一,线性表之单链表的实现。
下面给出具体的方法函数的实现:
#include "linklist.h"
void InitList(List *list){
//分配空间
list->first = list -> last = (Node*)malloc(sizeof(Node));
assert(list->first!=NULL);
//初始化几个数据域
list->first->next = NULL;
list->size = 0;
}
void push_back(List *list,ElemType x){
//分配空间
Node *s = (Node*)malloc(sizeof(Node));
assert(s!=NULL);
//对单个节点做初始化
s->data = x;
s->next = NULL;
//尾指针的下一个给到新节点
list->last->next = s;
//再任命新的节点为尾指针
list->last=s;
//数量增加
list->size++;
}
void push_front(List *list,ElemType x){
//分配空间
Node *s = (Node*)malloc(sizeof(Node));
assert(s!=NULL);
//初始化
s->data = x;
//两种情况:头插为第一个节点,则需要调整尾指针
//头插非,则只需要单纯插入不需要调整尾指针
//作插入操作
//先链接,新节点的next为目前的第一个节点
s->next = list->first->next;
//后断开,将目前的第一个节点改为新节点
list->first->next = s;
//如果size为1,则插入的为第一个节点
while(list->size == 0){
list->last = s;
}
//数量增加
list->size++;
}
void show_list(List *list){
//作展示
//将第一个节点给到p
Node* p = list->first->next;
//判断是否为空
while(p != NULL){
//不空则输出
//遍历节点的数据
printf("%d->",p->data);
//将指针指向下一个节点
p = p->next;
}
printf("\n");
}
void pop_back(List *list){
//尾部清除
//判断当前链表长度,为空不做处理
if(list->size == 0 ){
printf("当前链表为空");
return;
}
//将头节点的指针赋值给指针
Node *h = list->first;
//判断该指针的下一个是否和尾指针指向的节点一样
while(h->next != list->last){
//不一样则将指针不断往下面移动
h = h->next;
}
//一样了,则表示该指针的下一个为尾节点了
//可以释放尾指针指向的尾节点了
free(list->last);
//将尾指针指向改为刚刚循环遍历搞出来的原来的尾节点的前驱节点
list->last = h;
//将现在的尾节点的next设置为NULL
list->last->next =NULL;
//数量减少一个
list->size--;
}
void pop_front(List *list){
//判断表是否为空表
if(list->size == 0){
printf("这个是空表\n")
return;
}
//将头节点的指针传给h指针
Node *h = list->first;
//作头部弹出操作
//头节点指针的next设置为当前首节点的下一个,这样可以将前面的下面一个断开
list->first->next = h->next->next;
//释放掉之前的首节点
free(h->next);
//当释放掉首节点后表空的时候,需要调整尾节点的位置,因为释放的就是尾节点
while(list->size == 1){
list->last = list->first;
}
list->size--;
}
void insert(List *list,ElemType x){
//分配空间加上对节点的初始化
Node *s = (Node*)malloc(sizeof(Node));
assert(s!=NULL);
s->data=x;
s->next=NULL;
//将头节点指针给到p指针
Node *p = list->first;
//将p指针在next域不为空的情况下和下一个节点的数据小于x的情况下,将p指针后移
while(p->next!=NULL && p->next->data<x){
p=p->next;
}
//p指针移动到了尾节点
if(p->next == NULL){
//需要修改尾指针为目前这个新的节点
list->last = s;
}
//插入目前这个新的节点
//新节点的next改成之前的尾节点的next域
s->next = p->next;
//之前的尾节点改为倒数第二个节点,让他的next给到新节点
p->next = s;
list->size++;
}
Node *find(List *list,ElemType x){
//P指针赋值为首节点
Node *p = list->first->next;
//P指针从首节点开始,在P指针不为空的情况下和在P指针的数据域不为查找的数据的情况下,将p后移
while(p!=NULL && p->data!=x){
p=p->next;
}
//查到到了或者p到了最后一个节点的next,结束遍历
//如果p是最后一个的next,则返回的是NULL,否则返回的是有值的p
retun p;
}
int length(List *list){
return list->size();
}
void delete_val(List *list,ElemType key){
if(list->size == 0 ){
//当前为空表,无可删除
return;
}
//将list指针和查找的元素传进去,去获取要删除的节点
Node *p = find(list,key);
if(p==NULL){
printf("查找失败\n");
return;
}
//判断是否是尾节点,因为尾巴要改尾指针
if(list->last == p){
pop_back(list);
}else{
//使用覆法删除
p->data=p->next->data;
p->next=p->next->next;
free(p->next);
list->size--;
}
}
//排序
//利用插入进行排序
void sort(List *list){
//判断表是否为空表或者只有一个元素,如果如此,则不需要排序
if(list->size == 0||list->size == 1){
return;
}
//切割链表的首节点和之后的节点为两个链表
//将首节点指针给s,将首节点指针的下一个指针给q
Node *s = list->first->next;
//q这里开始可以独立成一个新的链表
Node *q = s->next;
//将首节点指针给到尾节点,
list->last=s;
//尾节点的下一个设置为空
list->last->next = NULL;
//判断链表二是否为空链表
while(q!=NULL){
//不空则开始将链表二的数据拿出来比较并且插入链表一
//q指针给到s
s=q;
//q指向下一个节点
q=q->next;
//将链表一的头节点给到p
Node *p = list->first;
//判断p的下一个是否为空,并且判断p的下一个的数据是否小于s的数据
while(p->next!=NULL&&p->next->data<s->data){
//如果成立,则p往后面移动,和后面的比较
p=p->next;
}
//比到了最后一个节点
if(p->next == NULL){
//该表链表一的尾指针为新节点s
list->last=s;
}
//作插入操作
//先链接,新节点的下一个设置为当前尾指针的下一个
s->next = p->next;
//老的尾节点的下一个设置为新的节点
p->next = s;
}
}
//倒置,使用头插法作倒置
void resver(List *list)
{
//数据表元素不够没有倒置的意义
if(list->size==0||list->size==1){
return;
}
//首节点给到p指针
Node* p =list->first->next;
//首届点的呃下一个节点给到q指针,用来标识一个新的链表二
Node *q = p->next;
//尾指针给到首节点处
list->last = p;
//开始和链表二断开,首节点的next设置为null
list->last->next = NULL;
//判断q指针是否为空,本质是判断链表二的首指针和之后不断遍历的新的指针是否为空
while(q!=NULL){
//不为空,开始作头部插入
//将当前节点给到p指针
p=q;
//再将q指针赋值为当前节点的下一个,用以下次的遍历判空
q=p->next;
//链表二的节点的next给到链表一的头节点的next
p->next = list ->first->next;
//链表一的头节点的下一个给到p
list->first->next=p;
}
}
//清除
void clear(List *list){
if(list->size ==0){
return;
}
//将首节点给到p
Node *p = list->first->next;
//判断p是否不为空,非空进行删除处理和往后遍历
while(p!=NULL){
//首节点给到当前p的下一个节点
list->first->next=p->next;
//释放p
free(p);
//p依旧代表首节点,不过首节点已经变了
p=list->first->next;
}
//尾指针回归
list->last=list->first;
//清除长度
list->size =0;
}
void destroy(List *list){
clear(list);
free(list->first);
list->first=list->last=NULL;
}