正好前两周写了个链表操作程序,可实现各种功能,自认为注释写的还算齐全,代码全贴给你吧,懒得删改了,大小排序部分看seque_list,可以选择不同模式按照从大到小,或者从小到大输出,打印直接调用print就可以了,就不明白追问就好了。
#include
#include
/*
Actor:qxliu
Date:17/04/17
实现单链表的各种操作,对链表结构深入理解;
1.创建链表;
2.表尾插入节点
3.表头插入节点
4.查找链表数值,并在其后插入新节点
5.查找链表数值,并删除该节点
6.链表逆序排列
7.打印链表节点
8.删除链表
9;链表按节点数值大小重排
*/
#define REVERSE_BYARRAY 0 //第一种方式逆序
#define REVERSE_BYDELETE 1
#define REVERSE_BYRECURSIVE 0
#define REVERSE_BYCYCLE 0
typedef struct node
{
int data;
struct node *next;
}Node;
extern void Print_list(Node* p);
Node *Phead=NULL;//表头全局指针
/*创建链表*/
void Creat_list_head()
{
int a=0;
static int flag=0;//表头创建标志
Node *p=(Node *)malloc(sizeof(Node));
if(NULL==p)
printf("Creat_list_head error!\n");
else
{
if(!flag)
{
printf("input num:");
scanf("%d",&a);
p->data=a;
p->next=NULL;
Phead=p;//表头指针被赋值,指向表头
}
else
printf("List_head has already created!\n");
}
}
/*复制链表*/
Node* Copy_list(Node *pindex)
{
Node *pback=NULL;
Node *p=pindex;
pback=(Node*)malloc(sizeof(Node));
if(NULL==pback||NULL==p)
{
printf("node error\n");
return;
}
while(p->next!=NULL)
{
pback->data=p->data;
pback->next=(Node *)malloc(sizeof(Node));
if(NULL==pback->next)
{
printf("creat node error\n");
return;
}
p=p->next;
pback=pback->next;
}
pback->data=p->data;//p->next==NULL时,最后一个data还未传递
pback->next=NULL;//避免复制的链表最后一个节点next野指针
pback=pindex;
return pback;
}
/*表尾插入新节点*/
void Insert_node_tail(int data)
{
Node* p=(Node *)malloc(sizeof(Node));
Node *ptail=Phead;//将表头指针赋值,从表头开始遍历
if(NULL==p)
printf("creat tail node error\n");
else
{
while(1)
{
if(NULL==ptail->next)//判断是否表尾,是则插入节点,否则继续遍历
{
p->data=data;
p->next=NULL;//新表尾
ptail->next=p;//将原表尾指向新表尾节点
return;
}
else
ptail=ptail->next;
}
}
}
/*表头插入节点,节点成为新表头*/
void Insert_node_head(int data)
{
Node *p=(Node *)malloc(sizeof(Node));
if(NULL==p)
printf("creat head node error\n");
else
{
p->data=data;
p->next=Phead;//链接旧表头
Phead=p;//更新新表头节点指针,以便其他函数使用
}
}
/*查值,然后在匹配的节点后插入新节点,默认链表中数值均不同*/
void Insert_node(int data)
{
int a=0;
Node *pindex=Phead;
Node *p=(Node *)malloc(sizeof(Node));
if(NULL==p)
printf("creat head node error\n");
else
{
printf("input insert_node data=");
scanf("%d",&a);
while(1)
{
if(pindex->data==data)//找到数值
{
p->data=a;
p->next=pindex->next;//原匹配节点的next成为插入新节点的next
pindex->next=p;//插入新节点后,原节点的next需指向新节点
return;
}
else
pindex=pindex->next; //继续遍历
}
}
}
void Value_del()
{
}
/*链表逆序排列的几种方式:
1.建立一个数组,遍历链表存储数值,然后通过数组逆序将值再次写入链表实现逆序
2.新建立一个链表,遍历旧链表至表尾,将值存入新链表,然后删除旧链表的尾节点,依次循环操作
3.新建立一个链表,使用递归函数遍将旧链表压栈,根据栈先进后出原则,将值依序存入新链表即可实现逆序
4.记录旧链表首尾节点,将旧链表尾链接至表头,然后依次转移节点,直到原表头next指向NULL;
*/
void Reverse_list(void)
{
#if REVERSE_BYARRAY //数组逆序法
int array[1024],i=0;
Node *pindex=Phead;
while(pindex->next!=NULL)//遍历至表尾,依次将链表数组存入数组
{
array[i]=pindex->data;
pindex=pindex->next;
i++;
}
array[i]=pindex->data;//当next==NULL时,循环不会进去,所以需要手动将尾节点数存入数组
pindex=Phead;//指向表头,再次遍历
while(pindex->next!=NULL)
{
pindex->data=array[i];
pindex=pindex->next;
i--;
}
printf("i=%d\n",i);
pindex->data=array[0];
#endif
#if REVERSE_BYDELETE
Node *pback,*pback_head;//pback为复制原始链表,操作均在pback进行,避免破坏 ,pback_head保存copy的表头
Node *pprev=NULL;//存放前一个节点值,因为单链表不能回溯
Node *pindex=(Node *)malloc(sizeof(Node));//新建立一个链表,存放逆序后的值
Node *pindexprev=pindex;//保存逆序链表头节点,方便打印;
if(NULL==pindex)
{
printf("creat head node error\n");
return;
}
pback=Copy_list(Phead);
pback_head=pback;
printf("********************source_list:\n");
Print_list(Phead);
printf("********************copy_list:\n");
Print_list(pback);
while(1)
{
while(pback->next!=NULL)
{
pprev=pback;
pback=pback->next;
}
pindex->data=pback->data;
pindex->next=(Node *)malloc(sizeof(Node));
pindex=pindex->next;
free(pback);//避免内存泄漏
pback=pprev;//前一个节点变成尾节点,所以需要pprev回溯以便next指向NULL
pback->next=NULL;
pback=pback_head;
if(pprev==pback_head)//pback已经删除到仅有一个节点时,逆序结束退出
{
pindex->next=NULL;
pindex->data=pback->data;//传值
break;
}
}
printf("***************reverse list:\n");
Print_list(pindexprev);
#endif
#if REVERSE_BYRECURSIVE
#endif
#if REVERSE_BYCYCLE //表头表尾法
Node *old_head_node=NULL,*old_tail_node=NULL,*pindex=NULL;//pindex 记录要移动的节点
old_head_node=Phead;//记录原表头,当原表头的old_head_node->next==NULL时候,逆序结束
pindex=Phead;
while(pindex->next!=NULL)//遍历至表尾
{
pindex=pindex->next;
}
old_tail_node=pindex;//记录原表尾
pindex->next=old_head_node;//指向原表头
while(old_head_node->next!=NULL)
{
if(pindex->next!=NULL)
pindex=pindex->next;
else
{
pindex->next=old_head_node;
old_tail_node->next=;//原表
}
}
#endif
}
/*打印链表*/
void Print_list(Node *p)
{
Node *pindex=p;
if(NULL==pindex)//空表,退出
{
printf("list not exist!!\n");
return;
}
else
while(pindex->next!=NULL)//遍历节点,打印
{
printf("list_value=%d,list_addr=%d,list_next=%d,\n",(int)pindex->data,(int)pindex,(int)pindex->next);
pindex=pindex->next;
}
printf("list_value=%d,list_addr=%d,list_next=NULL\n",(int)pindex->data,(int)pindex);
}
/*删除链表*/
void Del_list(Node *pindex)
{
Node* p=pindex;
Node* pback;
while(p->next!=NULL)
{
pback->next=p->next;//pback保存下一节点指针,避免P释放后断链的问题
p->next=NULL;
free(p);
p=pback->next;
}
free(p);
p->next=NULL;
}
//冒泡法进行排序
void seque_list(int mode)
{
Node *p=NULL;
Node *phead_back;
int count=0,cycle1=0,cycle2=0,value;
int num[9]={56,84,28,188,69,321,87,521,11};
for(cycle1=0;cycle1<9;cycle1++)
Insert_node_tail(num[cycle1]);
p=Copy_list(Phead);//避免破坏原链表
phead_back=p;
if(mode==0)
{
while(p->next!=NULL)
{
count++;
p=p->next;
}
printf("list_node_count=%d\n\n",count);
printf("original num:\n");
Print_list(phead_back);
for(cycle1=0;cycle1<=(count-1);cycle1++)
{
p=phead_back;
for(cycle2=0;cycle2<=(count-1);cycle2++)
{
if((p->data)>=(p->next->data))
{
value=p->data;
p->data=p->next->data;
p->next->data=value;
//printf("p->data=%d,p->next->data=%d\n",p->data,p->next->data);
}
p=p->next;
}
}
}
else if(mode==1)
{
while(p->next!=NULL)
{
count++;
p=p->next;
}
printf("list_node_count=%d\n",count);
for(cycle1=0;cycle1<=count;cycle1++)
{
p=phead_back;
for(cycle2=0;cycle2<=count;cycle2++)
{
if((p->data)<=(p->next->data))
{
value=p->data;
p->data=p->next->data;
p->next->data=value;
//printf("p->data=%d,p->next->data=%d\n",p->data,p->next->data);
}
p=p->next;
}
}
}
printf("\nnew num:\n");
Print_list(phead_back);
}
int main(int argc,char**argv)
{
int choice,a,mode;
while(1)
{
printf("*****************List Practice*****************\n\n");
printf("1. Creat list:\n");
printf("2. Insert new node to list tail:\n");
printf("3. Insert new node to list head:\n");
printf("4. Find vaule,insert new node:\n");
printf("5. Find vaule,delete node:\n");
printf("6. Reverse list:\n");
printf("7. Print list\n");
printf("8. Delete list:\n");
printf("9. Sequence list(min->max):\n");
printf("10.Sequence list(max->min):\n");
printf("11. Quit\n\n\n\n");
printf("select:");
scanf("%d",&choice);
switch(choice)
{
case 1:
Creat_list_head();
break;
case 2:
printf("input data:");
scanf("%d",&a);
Insert_node_tail(a);
break;
case 3:
printf("input data:");
scanf("%d",&a);
Insert_node_head(a);
break;
case 4:
printf("input data:");
scanf("%d",&a);
Insert_node(a);
break;
case 5:
Value_del();
break;
case 6:
Reverse_list();
break;
case 7:
Print_list(Phead);
break;
case 8:
Del_list(Phead);
break;
case 9:
mode=0;
seque_list(mode);
break;
case 10:
mode=1;
seque_list(mode);
break;
default:
break;
}
}
return 0;
}