一.普通头指针链表(头插法)
#include <stdio.h>
#include <stdlib.h>
//建立结点结构体
typedef struct node
{
int item;
struct node *next;
}node;
//头指针
node *head = NULL;
//给结点分配堆中空间
node *create_node(int data)
{
node *p=(node *)malloc(sizeof(node));
if(p==NULL)
{
printf("create failed\n");
exit(1);
}
p->item=data;
p->next=NULL;
return p;
}
//释放分配空间
void free_node(node *p)
{
free(p);
}
//添加结点到链表中
void insert_node(node *p)
{
p->next=head;
head=p;
}
//遍历链表
void travers_node()
{
node *p;
p=head;
while(p!=NULL)
{
printf("%d",p->item);
p=p->next;
}
printf("\n");
}
//查找结点
void find_node(int tar)
{
node *p=head;
while(p!=NULL)
{
if(p->item==tar)
{
printf("%p\n",p);
return ;
}
p=p->next;
}
printf("nothing\n");
return ;
}
//返回值是node的find函数
node *find2_node(int tar)
{
node *p=head;
while(p!=NULL)
{
if(tar==p->item)
{
return p;
}
p=p->next;
}
printf("can not find %d\n",tar);
}
//参数为node的删除函数
void remove_node(node *p)
{
node *pre;
pre=head;
if(p==head)
{
head=head->next;
p->next=NULL;
remove_node(p);
return ;
}
while(pre->next!=NULL)
{
if(pre->next==p)
{
pre->next=p->next;
p->next=NULL;
return ;
}
pre=pre->next;
}
}
//参数为数字的删除函数,其实与参数是结点的删除函数道理相同
void remove2_node(int des)
{
node *pre=head;
node *p=head->next;
if(head->item==des)
{
head=head->next;
pre->next=NULL;
free_node(pre);
return ;
}
while(p!=NULL)
{
if(p->item==des)
{
pre->next=p->next;
p->next=NULL;
free_node(p);
return ;
}
pre=pre->next;
p=p->next;
}
}
//销毁链表
void destory_node()
{
node*p;
while(head!=NULL)
{
p=head;
head=head->next;
free_node(p);
}
}
//翻转链表
void reverse_node()
{
node *p;
node *nhead=NULL;
while(head!=NULL)
{
p=head;
head=head->next;
p->next=nhead;
nhead=p;
}
head=nhead;
}
int main()
{
node *p;
p=create_node(1);
insert_node(p);
p=create_node(2);
insert_node(p);
p=create_node(3);
insert_node(p);
p=create_node(4);
insert_node(p);
p=create_node(5);
insert_node(p);
p=create_node(6);
insert_node(p);
travers_node();
find_node(1);
find_node(2);
find_node(10);
//移除之后释放
remove_node(p);
free_node(p);
travers_node();
remove2_node(3);
travers_node();
reverse_node();
travers_node();
destory_node();
travers_node();
return 0;
}
翻转:建立新的头指针,将原来链表的元素从头至尾取出,并头插到新头指针上,最后将新头指针赋给原头指针
二.普通头结点链表(头插法)
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int item;
struct node *next;
}node;
//建立一个哨兵头结点,为使之后操作均是使用“->”,初始化一个指向哨兵头结点的头指针head
node sentinel={0,NULL};
node *head=&sentinel;
//新建结点结构体,申请堆中内存
node *create_node(int data)
{
node *p=(node *)malloc(sizeof(node));
if(p==NULL)
{
printf("create failed");
}
p->item=data;
p->next=NULL;
}
//释放申请的内存
void free_node(node *p)
{
free(p);
}
void insert_node(node *p)
{
p->next=head->next;
head->next=p;
}
//顺序插入
void orderinsert_node(node *p)
{
node *pre=head;
while(pre->next!=NULL)
{
if(pre->next->item>=p->item)
{
break;
}
pre=pre->next;
}
p->next=pre->next;
pre->next=p;
}
//找结点,注意与头指针写法有所不同
node *find_node(int tar)
{
node *p=head->next;
while(p!=NULL)
{
if(p->item==tar)
{
return p;
}
p=p->next;
}
return NULL;
}
//头结点链表方便在此,不需要为删除第一个结点而重新写一套方案,删除所有的结点方法都是一样的
void remove_node(node *p)
{
node *pre=head;
while(pre->next!=NULL)
{
if(pre->next==p)
{
pre->next=p->next;
p->next=NULL;
return ;
}
pre=pre->next;
}
}
//遍历
void travers_node()
{
node *p=head->next;
while(p!=NULL)
{
printf("%d",p->item);
p=p->next;
}
printf("\n");
}
//翻转
void reverse_node()
{
node *p=NULL;
node *nhead=NULL;
while(head->next!=NULL)
{
p=head->next;
head->next=p->next;
p->next=nhead;
nhead=p;
}
head->next=nhead;
}
//销毁
void destory_node()
{
node *p=NULL;
while(head->next!=NULL)
{
p=head->next;
head->next=p->next;
free_node(p);
}
}
int main()
{
node *p;
p=create_node(1);
orderinsert_node(p);
p=create_node(2);
orderinsert_node(p);
p=create_node(3);
orderinsert_node(p);
p=create_node(4);
orderinsert_node(p);
p=create_node(5);
orderinsert_node(p);
p=create_node(6);
orderinsert_node(p);
travers_node();
p=find_node(3);
printf("%p %d\n",p,p->item);
remove_node(p);
free_node(p);
travers_node();
reverse_node();
travers_node();
destory_node();
travers_node();
return 0;
}
顺序插入:找一个元素,此元素比要插入元素大或者相等,则此元素放在插入元素之后,两个步骤:先找位置,找到后break,跳出循环,接着再进行插入步骤。