头文件 LinkList.h
#ifndef _LINKLIST_H_ //为了防止头文件的重复包含
#define _LINKLIST_H_
#include<stdio.h> //这样在测试文件中可以不引入这两个头文件
#include<stdlib.h>
typedef int datatype;
typedef struct node{
datatype data; //结点的数据域
struct node *next; //结点的指针域,指向其下一个结点
}listnode,*linklist;
linklist list_create1(); //创建一个空链表 ,返回一个指针型的结构体,也就是创建的链表的地址
linklist list_create2(); //创建一个可以用户自己输入数据的链表
int list_head_insert(linklist H,datatype value); //在头结点后面插入数据,输出顺序和输入顺序是反的
int list_insert(linklist H,int pos,datatype value); //按位置插入元素
int list_order_insert(linklist H,int pos,datatype value); //实现有序插入
int list_delete(linklist H,int pos); //删除链表中的一个元素
linklist list_get(linklist H,int pos); //按位置查找一个元素
linklist list_locate(linklist H,datatype value); //按值查找一个元素
void list_reverse(linklist H); //将链表反转
void list_sort(linklist H); //对单链表进行由小到大排序
void list_show(linklist H); //把链表的内容打印出来
linklist list_create1() //创建一个空链表,即只有头结点
{
linklist H;
if((H = (linklist)malloc(sizeof(listnode))) == NULL){
printf("malloc failed!\n");
return H;
}
H->data=0;
H->next=NULL;
return H;
}
linklist list_create2() //创建一个可以用户自己输入数据的链表 ,s输出是正序输出
{
linklist H,r,p;
int value;
//先创建一个空链表
if((H = (linklist)malloc(sizeof(listnode))) == NULL){
printf("malloc failed!\n");
return H;
}
H->data=0;
H->next=NULL;
r=H; //用一个指针指向链表头结点,方便后续插入元素,保证链表H指向头结点不变
while(1)
{
printf("please input a number(-1 exit):");
scanf("%d",&value);
if(value == -1){
break;
}
if((p = (linklist)malloc(sizeof(listnode))) == NULL){
printf("malloc failed!\n");
return H;
}
p->data=value;
p->next=NULL;
r->next=p;
r=p;
}
return H;
}
int list_head_insert(linklist H,datatype value) //在头结点后面插入数据
{
//因为是头部插入,所以顺序是反的
linklist p;
if((p = (linklist)malloc(sizeof(listnode))) == NULL){
printf("malloc failed!\n");
return -1;
}
p->data=value;
p->next=H->next;
H->next=p;
return 0; //插入成功返回0
}
int list_insert(linklist H,int pos,datatype value) //按位置插入元素
{
linklist p,q;
if(pos==0)
{
p=H;
}
else
{
p=list_get(H,pos-1); //使p指向要插入位置之前的一个元素
}
if(p == NULL)
{
printf("para is invalid\n");
return -1;
}
else
{
if((q = (linklist)malloc(sizeof(listnode))) == NULL)
{
printf("malloc failed\n");
return -1;
}
q->data=value;
q->next=p->next;
p->next=q;
return 0;
}
}
int list_order_insert(linklist H,datatype value) //实现有序插入
{
linklist p,q;
if((p = (linklist)malloc(sizeof(listnode))) == NULL)
{
printf("malloc failed!\n");
return -1;
}
p->data=value;
q=H;
while(q->next!=NULL && q->next->data < value)
{
q=q->next;
}
//循环结束后一种情况是q->next==NULL,要插入的数比所有结点值都大
//另一种情况是找到了合适的位置,从中间插入
p->next=q->next;
q->next=p;
return 0;
}
int list_delete(linklist H,int pos) //删除链表中的一个元素
{
linklist p,q;
if(pos==0)
{
p=H;
}
else
{
p=list_get(H,pos-1); //让指针指向要删除结点的前一个结点
}
if(p == NULL || p->next == NULL) //如果p以及p->next不存在,执行以下代码
{
printf("para is invalid\n");
return -1;
}
else
{
q=p->next; //q指向要删除结点
p->next=q->next; //让p指向要删除结点后的那个结点
free(q); //释放要删除结点的内存空间
q=NULL;
return 0;
}
}
linklist list_get(linklist H,int pos) //按位置查找一个元素
{
linklist p=H;
int i=-1; //因为链表下标从0开始
if(pos<0){
printf("position is invalid:<0\n");
return NULL;
}
while(p->next&&i<pos)
{
p=p->next;
i++;
}
// if(p->next)
if(i == pos)
{
return p;
}
else
{
printf("position is invalid: > length\n");
return NULL;
}
}
linklist list_locate(linklist H,datatype value) //按值查找一个元素
{
linklist p=H->next;
while(p && p->data != value)
{
p=p->next;
}
return p;
}
void list_reverse(linklist H) //将链表反转
{
linklist p,q;
p=H->next; //p指向结点 a0
H->next=NULL; // 将原链表置空
while(p!=NULL)
{
q=p;
p=p->next;
q->next=H->next;
H->next=q;
}
}
void list_sort(linklist H) //对单链表进行由小到大排序
{
linklist p,q,r;
//先把链表一分为2
p=H->next;
H->next=NULL;
//当p存在的时候,即H不为空链表
while(p)
{
q=p;
p=p->next;
r=H;
while(r->next!=NULL && r->next->data < q->data) //当r不等于空且指向的下一个结点值小于value
{
r=r->next;
}
//当循环结束r就指向了待插入的前一个结点
q->next=r->next;
r->next=q;
}
}
void list_show(linklist H) //把链表的内容打印出来
{
while(H->next) //只要H->next不等于空,来做遍历输出
{
printf("%d ",H->next->data);
H=H->next;
}
printf("\n");
}
#endif
测试文件:testLink.c
#include "LinkList.h"
int main()
{
linklist H,p; //声明一个结构体指针H
int pos,value;
H=list_create2(); //创建一个链表
list_show(H); //把链表内容打印出来
printf("===============================\n");
printf("请输入要查找的元素位置pos:");
scanf("%d",&pos);
if((p=list_get(H,pos)) != NULL)
{
printf("该位置的结点元素为:%d\n",p->data);
}
printf("===============================\n");
printf("请输入要查找的元素值value:");
scanf("%d",&value);
if((p=list_locate(H,value)) != NULL)
{
printf("找到该结点:%d\n",p->data);
}
else
{
printf("链表中无此结点\n");
}
printf("===============================\n");
printf("请输入要插入结点的结点位置pos和数据value:");
scanf("%d%d",&pos,&value);
if(list_insert(H,pos,value)==-1)
printf("插入失败!\n");
list_show(H);
printf("===============================\n");
printf("请输入要删除的结点位置pos:");
scanf("%d",&pos);
if(list_delete(H,pos) == -1)
{
printf("删除失败!\n");
}
list_show(H);
printf("===============================\n");
printf("输出从小到大排序后的单链表:\n");
list_sort(H);
list_show(H);
printf("===============================\n");
printf("下面实现有序插入,请输入要插入的值:\n");
scanf("%d",&value);
list_order_insert(H,value);
list_show(H);
printf("===============================\n");
printf("输出反序后的链表:\n");
list_reverse(H);
list_show(H);
return 0;
}
补充:
不带头结点的单链表反转
struct ListNode* list_reverse(struct ListNode *head){
if((head == NULL) || (head->next==NULL)) //链表为空,或只有一个结点(无需反转),直接返回
return head;
struct ListNode *pre, *cur, *ne;
pre = head; //将前面几个节点的地址依次保存在新定义的结构体指针
cur = head ->next;
while(cur)
{
ne = cur->next; //如果当前节点不为空,则将其指针域赋给ne指针
cur->next = pre; //直接将两个指针的指向反转
pre = cur; //将当前节点赋给pre,将三个指针在链表中的位子都往后移一位
cur = ne;
}
head->next = NULL;//将原来的第一个节点的指针域赋为空,作为尾节点
head = pre; //将原来的尾节点变成新链表的第一个节点
return head;
}