//List.h
/*****************************************
头插 尾插 显示 头删 尾删
按值插入 按位置插入 查找 长度
逆序 清除 摧毁 初始化 排序
按位置删除 按值删除
****************************************/
//代码可以进一步优化
#ifndef LIST_H_
#define LIST_H_
#include <stdio.h>
typedef int ElementType;
typedef enum
{
false_,
true_
}bool_;
//链表的各节点类型
typedef struct Node
{
ElementType data;
struct Node *next;
}Node, *pNode;
//链表的管理结构
typedef struct List
{
Node *first; //指向头结点
Node *last; //指向最后一个节点,用于在某些时候避免不必要的遍历,如尾部插入
int size; //链表除头结点的个数
}List, *pList;
bool_ init(List *mylist);
bool_ push_fornt(List *mylist, ElementType e);
bool_ push_back(List *mylist, ElementType e);
void show(List mylist);
bool_ pop_fornt(List* mylist, ElementType *e);
bool_ pop_back(List* mylist, ElementType *e);
bool_ insert_val(List *mylist, ElementType e);
bool_ insert_pos(List *mylist, int i, ElementType e);
Node *find(List mylist, ElementType e, bool_ precursor);
int length(List mylist);
void reverse(List *mylist);
void clear(List *mylist);
void destroy(List *mylist);
void sort(List *mylist);
bool_ delete_pos(List *mylist, int i, ElementType *e);
bool_ delete_val(List *mylist, ElementType e);
#endif //LIST_H_
//List.c
#include "List.h"
#include "stdlib.h"
bool_ init(List *mylist)
{
mylist->last = mylist->first = (Node *)malloc(sizeof(Node));
if( NULL == mylist->first )
{
return false_;
}
mylist->first->next = NULL;
mylist->first->data = -1;
mylist->size = 0;
return true_;
}
bool_ push_fornt(List *mylist, ElementType e)
{
Node *p = (Node *)malloc(sizeof(Node));
if( NULL == p )
return false_;
p->next = NULL;
p->data = e;
p->next = mylist->first->next;
mylist->first->next = p;
if( 0 == mylist->size )
mylist->last = p; //链表为空时,新节点也是尾节点
mylist->size++;
return true_;
}
bool_ push_back(List *mylist, ElementType e)
{
Node *s = NULL;
Node *p = (Node *)malloc(sizeof(Node));
if( NULL == p )
return false_;
p->data = e;
p->next = NULL;
mylist->last->next = p;
mylist->last = p; //注意更改尾指针
mylist->size++;
return true_;
}
void show(List mylist)
{
Node *p = mylist.first->next;
while(NULL != p)
{
printf("%d->", p->data);
p = p->next;
}
printf("NULL\n");
printf("尾节点的值为%d\n", *mylist.last);
}
bool_ pop_fornt(List* mylist, ElementType *e)
{
if( 0 == mylist->size)
{
printf("链表为空\n");
return false_;
}
Node *p = mylist->first->next;
mylist->first->next = p->next;
*e = p->data;
free(p);
if( 1== mylist->size ) //亦可通过比较p与last指针判断
mylist->last = mylist->first; //处理尾指针
mylist->size--;
return true_;
}
bool_ pop_back(List* mylist, ElementType *e)
{
if( 0 == mylist->size )
{
printf("链表为空\n");
return false_;
}
Node *p = mylist->first;
while(p->next != mylist->last)
p = p->next; //寻找尾节点前驱节点
*e = mylist->last->data;
free(mylist->last);
mylist->last = p;
p->next = NULL;
mylist->size--;
return true_;
}
bool_ insert_val(List *mylist, ElementType e) //此函数的先决条件:链表中已存在节点的数据域值必须有序
{
if( 0 == mylist->size )
return push_back(mylist, e);
Node *v = (Node *)malloc(sizeof(Node));
if( NULL == v )
return false_;
v->next = NULL;
v->data = e;
Node *p = mylist->first;
while(NULL != p->next && p->next->data < e) //寻找位置,找到后p的数据域值小于e,p的后继数据域大于e
p = p->next;
if( NULL == p->next )
mylist->last = p; //尾指针
v->next = p->next; //使存有e的节点在p的原后继节点之前,p节点之后
p->next = v;
mylist->size++;
return true_;
}
//指定头结点为第0个位置,在第1个位置插入,则插入完成后的第1个位置即为新节点
bool_ insert_pos(List *mylist, int i, ElementType e)
{
if( i < 1 )
{
printf("输入位置小于1, 已插入为第一个节点\n");
return push_fornt(mylist, e);
}
if( i > mylist->size + 1 )
{
printf("输入的位置大于链表范围,已插入为尾节点\n");
return push_back(mylist, e);
}
Node *v = (Node *)malloc(sizeof(Node));
if( NULL == v )
return false_;
v->data = e;
v->next = NULL;
Node *p = mylist->first;
for(int j = 1; j < i; j++) //寻找合适的位置
{
p = p->next;
}
v->next = p->next;
p->next = v;
mylist->size++;
return true_;
}
Node *find(List mylist, ElementType e, bool_ precursor) //precursor为真时返回e节点的前驱节点指针值
{
if( 0 == mylist.size )
return NULL;
Node *p = mylist.first;
while(NULL != p->next && p->next->data != e)
p = p->next;
if( NULL == p->next )
return NULL;
else
return precursor ? p : p->next;
}
int length(List mylist)
{
return mylist.size;
}
//将链表分成两个链表(链表1有头结点与1节点,链表2为剩余节点的链表)后,将链表2的节点逐个头插入链表1
void reverse(List *mylist)
{
if( 0 == mylist->size || 1 == mylist->size )
return ;
Node *p = mylist->first->next;
Node *q = p->next;
p->next = NULL; //拆分链表
mylist->last = p; //处理尾指针
while(NULL != q) //将p的节点逐个插入到头结点之后
{
p = q; //p指向当前意图插入的节点
q = q->next; //q继续持有链表2
p->next = mylist->first->next; //按计划插入
mylist->first->next = p;
}
}
void clear(List *mylist)
{
if( 0 == mylist->size )
return ;
Node *p = mylist->first->next;
mylist->last = mylist->first; //尾指针
while( NULL != p)
{
mylist->first->next = p->next;
free(p);
p = mylist->first->next;
}
mylist->size = 0; //!!!
}
void destroy(List *mylist)
{
clear(mylist);
free(mylist->first);
mylist->first = mylist->last = NULL;
}
//拆分后按序插入,还是跟之前一样拆成两个链表,链表1只含头结点和1节点,链表2含后续节点
void sort(List *mylist)
{
if( 0 == mylist->size || 1 == mylist->size )
return ;
Node *p = mylist->first->next;
Node *q = p->next; //q指向链表2
mylist->last = p; //尾指针
p->next = NULL; //拆分链表
Node *s = mylist->first; //s指向链表1
while(NULL != q) //将链表2的节点逐个插入到链表1
{
while(NULL != s->next && s->next->data < q->data) //以链表2中的首个节点的数据域去根据顺序查它应该位于链表1的什么位置
{
s = s->next;
}
if( NULL == s->next ) //链表1中的全部节点数据域都小于q节点
mylist->last = q; //处理尾指针
p = q; //用p指向待插入节点
q = q->next; //q继续持有链表2
p->next = s->next; //按计划插入
s->next = p;
s = mylist->first; //令s重新指向链表1
}
}
bool_ delete_pos(List *mylist, int i, ElementType *e)
{
int j = 0;
Node *p = mylist->first;
Node *q = NULL;
if( 0 == mylist->size )
{
printf("链表为空\n");
return false_;
}
if( i < 1 || i > mylist->size )
{
printf("指定的 删除位置不合法,请重新选择\n");
return false_;
}
for(j = 1; j < i; j++)
{
p = p->next;
}
q = p->next; //目标删除节点
p->next = q->next;
*e = q->data;
if( NULL == q->next ) //当q为尾节点
mylist->last = p; // 尾
free(q);
mylist->size--;
return true_;
}
bool_ delete_val(List *mylist, ElementType e)
{
Node * p = NULL, *q = NULL;
if( NULL == ( p = find(*mylist, e, true_)) ) //查找目标节点的前驱节点
{
printf("需要删除的节点不存在\n");
return false_;
}
q = p->next; //目标节点
p->next = q->next;
if( NULL == q->next )
mylist->last = p; // 尾
free(q);
mylist->size--;
return true_;
}
//main.c
/*****************************************
头插 尾插 显示 头删 尾删
按值插入 查找 长度 按值删除 排序
逆序 清除 摧毁 初始化 按位置插入
按位置删除
****************************************/
#include "List.h"
int main(int argc, char**argv)
{
int s = 0;
ElementType e;
List mylist;
init(&mylist);
while(1)
{
printf("/******************************************************/\n");
printf("1头插 2尾插 3显示 4头删 5尾删\n");
printf("6按值插入 7查找 8长度 9按值删除 10排序\n");
printf("11逆序 12清除 13摧毁 14按位置删除 15按位置插入\n");
printf("16初始化 17退出\n");
printf("/******************************************************/\n");
printf("请选择操作, -1退出\n");
if( 0 == scanf_s("%d", &s) )
break;
switch(s)
{
case 1:
printf("请输入待插入的值, -1退出\n");
while (scanf_s("%d", &e), e != -1)
push_fornt(&mylist, e);
break;
case 2:
printf("请输入待插入的值, -1退出\n");
while (scanf_s("%d", &e), e != -1)
push_back(&mylist, e);
break;
case 3:
show(mylist);
break;
case 4:
if( false_ != pop_fornt(&mylist, &e))
printf("被删除的值是%d\n", e);
break;
case 5:
if (false_ != pop_back(&mylist, &e))
printf("被删除的值是%d\n", e);
break;
break;
case 6:
printf("请输入待插入的值, -1退出\n");
while (scanf_s("%d", &e), e != -1)
insert_val(&mylist, e);
break;
case 7:
printf("请输入需查找的值\n");
scanf_s("%d", &e);
printf("返回待查值的前驱节点?否:0,是:非0\n");
scanf_s("%d", &s);
if( NULL == find(mylist, e, s) )
printf("查找的值不存在\n");
break;
case 8:
printf("链表长度为%d\n", length(mylist));
break;
case 9:
printf("请输入待删除的值\n");
scanf_s("%d", &e);
delete_val(&mylist, e);
break;
case 10:
sort(&mylist);
break;
case 11:
reverse(&mylist);
break;
case 12:
clear(&mylist);
break;
case 13:
destroy(&mylist);
break;
case 14:
printf("请输入待删除位置\n");
scanf_s("%d", &s);
if( false_ != delete_pos(&mylist, s, &e) )
printf("被删除的值为%d\n", e);
break;
case 15:
printf("请输入待插入位置\n");
scanf_s("%d", &s);
printf("请输入待插入值");
scanf_s("%d", &e);
insert_pos(&mylist, s, e);
break;
case 16:
init(&mylist);
break;
case 17:
goto exit;
default:
printf("选择有误,请从新选择\n");
break;
}
}
exit:
return 1;
}