这两天上课正好做到关于链表的一些操作,所以就把自己写的一些东西记录下来了
代码如下,不足之处望大家指正,旨在共同学习进步O(∩_∩)O~
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//定义链表的结构体
typedef struct node
{
int data;
struct node *next;
}node;
//遍历输出链表
void print(node *s)
{
//利用一个中间节点来遍历链表并输出
node *temp;
temp=s->next;
while(temp!=NULL)
{
printf("%d ",temp->data);
temp=temp->next;
}
printf("\n");
}
//查找元素
void find(node *s,int destination)
{
//利用一个中间节点来遍历链表并输出
node *temp;
temp=s->next;
while(temp!=NULL)
{
if(temp->data==destination)
{
printf("存在该元素!\n");
return;
}
temp=temp->next;
}
printf("不存在该元素!\n");
printf("\n");
}
//插入节点
node *add(node *s,int number)
{
node *temp_list;
for(int i=0;i<number;i++)
{
if(temp_list==NULL)
{
printf("error!\n");
exit(1);
}
temp_list=(node *)malloc(sizeof(node));
temp_list->data=rand()%100+1;
temp_list->next=s->next;
s->next=temp_list;
}
return s;
}
//删除节点
node *del(node *s,int number)
{
node *temp;
for(int i=0;i<number;i++)
{
//保存头结点指针域
temp=s->next;
//删除节点
s->next=(s->next)->next;
temp->next=NULL;
//(s->next)->next=NULL;
//s=s->next;
}
return s;
}
int main(void)
{
//创建头结点
node *head;
node *list;
srand(time(0));
head=(node *)malloc(sizeof(node));
//错误处理
if(head==NULL)
exit(1);
head->next=NULL;
//创建链表(头插法)
list=(node *)malloc(sizeof(node));
head->next=list;
list->data=rand()%100+1;
list->next=NULL;
for(int i=0;i<9;i++)
{
//错误处理
if(list==NULL)
{
printf("error!\n");
exit(1);
}
list=(node *)malloc(sizeof(node));
list->data=rand()%100+1;
list->next=head->next;
head->next=list;
}
print(head);
int operate;
printf("请输入要执行的操作(1.插入,2.删除,3.查找,4.退出):");
while(scanf("%d",&operate)==1)
{
switch(operate)
{
case 1:{
int add_number;
printf("请输入要插入节点的个数:");
scanf("%d",&add_number);
head=add(head,add_number);
print(head);
};break;
case 2:{
int delete_number;
printf("请输入要删除的节点个数:");
scanf("%d",&delete_number);
head=del(head,delete_number);
print(head);
};break;
case 3:{
int number;
printf("请输入要查找的元素:");
scanf("%d",&number);
find(head,number);
};break;
default:exit(1);
}
printf("请输入要执行的操作(1.插入,2.删除,3.查找,4.退出):");
}
free(head);
free(list);
return 0;
}
以下是调试的结果(这里我用的都是随机的方法生成的数字):
继续上次的实验内容
这一次是添加了一个排序的功能(将两个链表合并之后进行升序的排列)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SWAP(a,b,c) ((c)=(a),(a)=(b),(b)=(c))
//定义链表的结构体
typedef struct node
{
int data;
struct node *next;
}node;
void print(node *s)
{
node *m;
m=s->next;
while(m!=NULL)
{
printf("%-2d ",m->data);
m=m->next;
}
printf("\n");
}
int main(void)
{
//创建两个链表
node *head1;
node *head2;
node *list1;
node *list2;
//创建表1
head1=(node *)malloc(sizeof(node));
head1->next=NULL;
list1=(node *)malloc(sizeof(node));
srand(time(0));
list1->data=rand()%100+1;
head1->next=list1;
list1->next=NULL;
for(int i=0;i<9;i++)
{
list1=(node *)malloc(sizeof(node));
list1->data=rand()%100+1;
list1->next=head1->next;
head1->next=list1;
}
printf("表1内容:\n");
print(head1);
//
//创建表2
head2=(node *)malloc(sizeof(node));
list2=(node *)malloc(sizeof(node));
list2->data=rand()%100+1;
head2->next=list2;
list2->next=NULL;
for(int j=0;j<9;j++)
{
list2=(node *)malloc(sizeof(node));
list2->data=rand()%100+1;
list2->next=head2->next;
head2->next=list2;
}
printf("表2内容:\n");
print(head2);
///
//合并两个链表
node *head3;
head3=head1->next;
while(head3!=NULL)
{
if(head3->next==NULL)
{
head3->next=head2->next;
break;
}
head3=head3->next;
}
printf("合并之后的内容:\n");
print(head1);
///
//排序(选择排序)
int temp;
node *m=head1->next;
node *n=NULL;
while(m!=NULL)
{
n=m->next;
while(n!=NULL)
{
if(m->data>n->data)
SWAP(m->data,n->data,temp);
n=n->next;
}
m=m->next;
//n=m->next;
}
printf("排序之后的内容:\n");
print(head1);
///
free(head1);
free(head2);
free(head3);
free(list1);
free(list2);
free(m);
free(n);
return 0;
}
下面的运行结果(节点数我是一次性设置了十个,也可以自己修改一下,做一个任意设置的,数字也是随机生成的):
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
上面用的是头插法产生的链表,再输出的时候会差生一个问题(手动输入数据的话),就是反着输出来
所以现在用尾插法来修改一下,并且对之前不能在任意位置进行插入和删除节点也做了修改,具体的代码如下(新添加一个链表就地逆置的函数):
#include <stdio.h>
#include <stdlib.h>
int length;//链表的长度
typedef struct node{
int data;
struct node *next;
}node;
#define SWAP(a,b,c) ((c)=(a),(a)=(b),(b)=(c))
//
//创建链表(尾插法)
node *create(node *s){
node *list,*p,*q;
p=s;
printf("请输入要建立的链表的长度:");
while(scanf("%d",&length)!=1);
printf("请依次输入链表元素:\n");
list=(node *)malloc(sizeof(node));
p->next=list;
scanf("%d",&list->data);
list->next=NULL;
for(int i=0;i<length-1;i++){
//临时节点
q=list;
//申请新的节点
list=(node *)malloc(sizeof(node));
scanf("%d",&list->data);
//前驱的指针域指向新的节点
q->next=list;
//新节点的指针域置空
list->next=NULL;
//list=q;
}
return s;
}
//打印链表
void print(node *s){
node *p;
p=s->next;
while(NULL!=p){
printf("%-3d",p->data);
p=p->next;
}
printf("\n");
}
//链表排序
void sort(node *s){
node *p,*q;
p=s;
int temp;
while(NULL!=p){
q=p->next;
while(NULL!=q){
if(p->data>q->data)
SWAP(p->data,q->data,temp);
q=q->next;
}
p=p->next;
}
}
//插入元素
node *insertion(node *s){
int number,pos;
node *p;//记录插入位置的前驱
node *temp;//新插入的节点
p=s;
temp=(node *)malloc(sizeof(node));
printf("请输入要进行插入的位置:");
//输入并做错误处理
while(scanf("%d",&pos)==1&&pos>=1&&pos<=length){
for(int i=1;i<pos;i++)
p=p->next;
printf("请输入插入的值:\n");
while(scanf("%d",&number)!=1);
temp->data=number;
temp->next=p->next;
p->next=temp;
break;
}
length++;//插入之后,链表长度加1
return s;
}
//删除元素
node *_delete(node *s){
int pos;
node *p,*q;
p=s;
printf("请输入要删除的位置:");
//错误处理
while(scanf("%d",&pos)!=1&&pos>length);
for(int i=1;i<pos;i++){
//存储前驱
p=p->next;
}
//存下删除的位置
q=p->next;
p->next=q->next;
length--;//链表长度减1
return s;
}
//查找元素
void search(node *s){
int number;
node *temp=s->next;
printf("请输入要查找的元素:");
while(scanf("%d",&number)!=1);
while(NULL!=temp){
if(number==temp->data){
printf("存在该元素!\n");
return;
}
temp=temp->next;
}
printf("不存在该元素!\n");
return ;
}
//就地逆序置换链表的函数
void transport(node *list)
{
node *p,*q,*s;
//头指针不为空则进行置换
if(NULL != list)
{
//记录下首元素的节点和第二个节点
p = list->next;
q = p->next;
//头指针置空
list->next = NULL;
//首元素置空,起始端做终点端
p->next = NULL;
while(q)
{
//暂存下一个节点
s = q->next;
//next域逆置
q->next = p;
//指针后移
p = q;
q = s;
}
list->next = p;
}
}
//销毁链表
void destory(node *s){
node *temp;
node *q;
temp=s->next;
while(NULL!=temp){
//存储下一个节点
q=temp->next;
//释放当前节点
free(temp);
//节点后移一位
temp=q;
}
}
int main(void){
node *head;
head=(node *)malloc(sizeof(node));
head->next=NULL;
//创建链表
head=create(head);
print(head);
/
//链表排序
int temp;
printf("是否进行排序(1.是,2.否):");
scanf("%d",&temp);
if(1==temp){
printf("排序之后如下所示:\n");
sort(head);
print(head);
}
/
int position;
printf("请输入要进行的操作(1.插入,2.删除,3.查找,4.逆序置换,5.退出):");
while(scanf("%d",&position)==1){
switch(position){
case 1:head=insertion(head);print(head);break;
case 2:head=_delete(head);print(head);break;
case 3:search(head);break;
case 4:transport(head);print(head);break;
default:exit(0);
}
printf("请输入要进行的操作(1.插入,2.删除,3.查找,4.逆序置换,5.退出):");
}
/
//销毁链表
destory(head);
free(head);
return 0;
}
运行结果截图:
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
继续更新,这次是循环链表的操作,一个是建立一个循环链表,然后求出循环链表的长度(这里没有手动输入,手动输入的话稍微修改一下就行了),还有在首元素的节点之后插入一个新的节点的操作,代码如下:
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *next;
}node;
void print(node *s)
{
node *temp = s->next;
do
{
printf("%-3d",temp->data);
temp=temp->next;
}while(s->next != temp);
}
//求循环链表的长度
int f(node *s)
{
int count = 0;
node *temp = s->next;
do
{
count ++;
temp = temp->next;
}while(s->next != temp);
return count;
}
//表头插入节点
void insert(node *s)
{
int a;
node *temp = s->next;
node *insertion;
insertion = (node *)malloc(sizeof(node));
printf("请输入插入的元素:");
scanf("%d",&a);
insertion->data = a;
insertion->next = temp->next;
temp->next = insertion;
}
void destory(node *s)
{
node *p = s->next,*q;
//循环链表的终止条件要注意
while(s->next != p)
{
q = p->next;
free(p);
p = q;
}
}
int main(int argc,char *args[])
{
node *head,*list,*p;
head = (node *)malloc(sizeof(node));
head->next = NULL;
list = (node *)malloc(sizeof(node));
head->next = list;
list->data = 1;
list->next = NULL;
p = list;
for(int i=1;i<=9;i++)
{
list = (node *)malloc(sizeof(node));
list->data = i+1;
//链接新的节点
p->next = list;
list->next = NULL;
//存储新节点作为下一节点的前驱
p = list;
}
//终端端点链接首节点
list->next = head->next;
print(head);
printf("\nThe length of the node table is:%d\n",f(head));
insert(head);
print(head);
printf("\nThe length of the node table is:%d\n",f(head));
destory(head);
free(head);
return 0;
}
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
课余时间继续更新,这次更新的是双向循环链表的相关操作(包括插入,删除,查找,以及创建一个和销毁一个双向循环链表的操作),由于双向循环链表的独特结构,所以在插入和删除操作的时间复杂度上都能达到常量级别,并且每个节点还有一个指针域指向自己的前驱,所以查找的话效率也会增加一些的,具体代码实现如下:
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
struct node *llink;
int data;
struct node *rlink;
}node;
void create(node *s)
{
node *list,*temp;
list = (node *)malloc(sizeof(node));
list->data = 1;
s->llink = NULL;
s->rlink = list;
list->rlink = NULL;
for(int i = 2;i <= 10;i ++)
{
//暂存一个节点
temp = list;
list = (node *)malloc(sizeof(node));
list->data = i;
list->llink = temp;
temp->rlink = list;
list->rlink = NULL;
}
list->rlink = s;
s->llink = list;
}
void print(node *s)
{
node *temp = s->rlink;
while(s != temp)
{
printf("%-3d",temp->data);
temp = temp->rlink;
}
printf("\n");
}
void destory(node *s)
{
node *p = s->rlink,*q = p->rlink;
while(s != q)
{
free(p);
p = q;
//暂存下一个节点
q= q->rlink;
}
}
void insert(node *s)
{
int number;
node *temp = s->rlink;
node *newnode;
newnode = (node *)malloc(sizeof(node));
printf("请输入要插入的元素值:");
while(scanf("%d",&number) != 1);
newnode->data = number;
newnode->rlink = temp->rlink;
newnode->llink = temp;
temp->rlink->llink = newnode;
temp->rlink = newnode;
}
void del(node *s)
{
node *temp = s->rlink;
s->rlink = temp->rlink;
s->rlink->llink = NULL;
free(temp);
}
void search(node *s)
{
int number;
printf("请输入要查找的元素值:");
while(scanf("%d",&number) != 1);
node *temp = s->rlink;
node *p = s->llink;
//从双向链表的两端开始进行搜索
while(p != temp)
{
if(number == temp->data||number == p->data)
{
printf("found!\n");
return;
}
temp = temp->rlink;
p = p->llink;
}
if(number == temp->data||number == p->data)
{
printf("found!\n");
return;
}
printf("not found!\n");
}
int main(int argc,char *args[])
{
node *head;
head = (node *)malloc(sizeof(node));
create(head);
print(head);
int pos;
printf("请输入要执行的操作(1.插入,2.删除,3.查找,4.退出):");
while(scanf("%d",&pos) == 1)
{
switch(pos)
{
case 1:insert(head);print(head);break;
case 2:del(head);print(head);break;
case 3:search(head);print(head);break;
default:exit(0);
}
printf("请输入要执行的操作(1.插入,2.删除,3.查找,4.退出):");
}
destory(head);
free(head);
return 0;
}
下面是调试的结果截图:
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
有不足之处望大家指正,如果大家还有什么好的想法也可以提出来~~~