数据结构——单链表

#include <stdio.h>
#include <stdlib.h>

/* 单链表的简单代码 */

/* 此步骤为建立对应的表格结构 */
struct list {		
	int number;
	struct list *next;

};

/* ?若不定义转换,在sizeof(struct list)会报错 */
typedef struct list LIST;


/* 此步骤为创建链表函数,需要用到head p1,p2三个指针 */ 
LIST *creat(int n)
{
	int i,x;
	LIST *head,*p1,*p2;
	head=NULL;
	for(i=0;i<n;i++)
	{
		p1=(LIST*)malloc(sizeof(LIST));
		printf("请输入第%d个数: ",i);
		scanf("%d",&x);
		p1->number=x;
		if(head==NULL)
		{
			head=p1;p2=p1;
		} 
		else
		{
			p2->next=p1;
			p2=p1;
		}
		p2->next=NULL;
	}
	return head;     
}


/* 此步骤为输出函数 */
void output(LIST *p)
{
	int i=0;
	LIST *q;
	while(p!= NULL)
	{
		printf("第%d个数是: %d\n",i+1,p->number);
		q=p->next;
		p=q;
		i++;
		
	}

	
}



/* 此步骤为添加内容函数,为保证可读性,存在问题:输入n为0或者为负时,无改变表头和报错 */
void additem(LIST *p)
{
	int n,i,x;
	LIST *q;
	printf("请输入要插入在第几个数据后:");
	scanf("%d",&n);
	printf("请输入要插入的数据:");
	scanf("%d",&x);

//	if(n=0)
//	{
//		q=(LIST*)malloc(sizeof(LIST));
//		q->number=x;
//		q->next=p;
//注释:此步未完成,为便于自己理解基本结构
//	}
//	if(n<0){
//	}
	for(i=0;i<n-1;i++)     /* 此处i=n-1   比如删除第5位数据,即删除a[4],此时i从0遍历,i=0循环完,p指向a[1],i=4循环完,p指向a[5] 下面删除元素同理 */
	{
		q=p->next;
		p=q;
	}
	q=(LIST*)malloc(sizeof(LIST));
	q->number=x;
	q->next=p->next;
	p->next=q;

}

/* 此步骤为删除元素,同样没有健壮性处理 */
void del(LIST *p) 
{
	int n,i;
	LIST *q1,*q2;
	printf("请输入要删除的元素位数:");
	scanf("%d",&n);
	for(i=0;i<n-1;i++)
	{
		q1=p->next;
		q2=p;
		p=q1;
	} 
	
	q1=p->next;  			 /* 此步骤完成之后 q1是n+1位置;q2是n-1位置;p则是n的位置 */
	q2->next =q1; 			 /* 将p元素删除去 */
	free(p);				 /* 此步骤必不可少,易忘 */

}

 
/* 此步骤为删除整个函数,必不可少的一步,case 4 case 5均需要 */
void free_list(LIST *p) 
{
	LIST *q;
	while(p!=NULL)
	{
		q=p->next;
		free(p);
		p=q;
	}
	
	
}

/* 补充部分:重组链表,分治为两个链表  */
LIST *A_B(LIST *p)
{
	LIST *q,*head,*temp;
	head=p->next;
	q=p->next;
	while(p->next!=NULL)
	{
		temp=p->next;      		  /*temp为临时节点 */ 
		p->next=temp->next;	 	 /*重新构造p节点,跨过原来的下一位来构筑 */ 
		temp=p->next;			/*使临时节点指向q之后的节点,用于连接链2 */ 
		q->next=temp;				/* 重新链接链2*/ 
		q=q->next; 
	} 
	q->next =NULL;
	p->next=NULL;
	
	
	return head;
	
}





/* 此步骤为输主函数,链表过程实现全部由子函数完成 */
int main(int argc, char *argv[]) {
	LIST *p;
	int n,select;
	remake:
	printf("请输入链表长度:");
	scanf("%d",&n);
	p=creat(n); 
	printf("链表建立完成!\n");
	selection:
	printf("=====================================\n");
	printf("请按以下提示操作:\n"
			"0.退出程序\n"
			"1.顺序输出链表\n" 
			"2.插入数据\n"
			"3.删除数据\n"
			"4.重建链表\n"
			"5.删除链表\n");
	scanf("%d",&select);
	printf("=====================================\n\a");
	switch(select)
	{

		case 1:
			output(p);
			break;
		case 2:
			additem(p);
			break;
		case 3:
			del(p);
			break;
		case 4:
			free_list(p);
			goto remake; 
			break;
		case 5:
			free_list(p); 
			break;
		case 0:
			return 0;
		default:
			printf("你输入了错误的代码!\n\a");
	}
	goto selection; 
	
	return 0;
}



 补充:

1.上述代码创建链表采用尾插法——用一个指针始终指向尾部,在尾部构建后续链表。

在此补充另一种建表方式——头插法,即每次新数据在原有前方插入,代码如下:

/* 头插法 */ 
LIST *creat(int n)
{


	int i,x;
	LIST *q,*p;
	q=(LIST*)malloc(sizeof(LIST));
	q->next=NULL;
	for(i=0;i<n;i++)
	{
		p=(LIST*)malloc(sizeof(LIST));  
		printf("请输入第%d个数: ",i);
 		scanf("%d",&x);
 		p->number=x; 
		p->next=q->next;
		q->next=p;						/* 在q与q->next两个之间插入数值,新的q->next变为插入的数 */ 
	}
	
	
	return p;  /*此处也可返回q用来表示空的头结点*/ 
}


2.关于头结点:

创建头结点,有时候会是删除、插入等各种操作(如上删除操作,如果删除第一个链,没有头结点的时候非常麻烦,还要重新定头等)的时候更加便于理解,特别是在比较复杂的链表中。




                
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值