数据结构——链表的操作

3 篇文章 0 订阅
2 篇文章 0 订阅

这两天上课正好做到关于链表的一些操作,所以就把自己写的一些东西记录下来了

代码如下,不足之处望大家指正,旨在共同学习进步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;
}

下面是调试的结果截图:


---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

有不足之处望大家指正,如果大家还有什么好的想法也可以提出来~~~


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值