C语言学习——单链表

今天学习了单链表的增(创建)删改查的操作。

创建链表,共有头插法、尾插法、和有序插入法(中间插入)三种。

1.头插法创建无头链表(头节点中存数据):无头链表似乎在其他的操作上会比较麻烦,因为要单独处理头节点的数据。

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

struct node{
	int data;
	struct node *next;
};

void link_head_insert(struct node** phead,struct node** ptail,int n){
	struct node* pnew = (struct node*)malloc(sizeof(struct node));
	memset(pnew, 0, sizeof(struct node));
	pnew->data = n;
	if (*phead == NULL){
		*phead = pnew;
		*ptail = pnew;
	}
	else{
		pnew->next = *phead;
		*phead = pnew;
	}
}

void link_print(struct node* phead){
	struct node* pcur;
	pcur = phead;
	while (pcur != NULL){
		printf("%3d ", pcur->data);
		pcur = pcur->next;
	}
	printf("\n");
}


int main(){
	struct node *phead, *ptail;
	int num;
	phead = NULL;
	ptail = NULL;
	while (scanf("%d", &num) != EOF){
		link_head_insert(&phead, &ptail, num);
	}
	link_print(phead);
	reverse(phead);
	link_print(phead);

	system("pause");
	return 0;
}


2.尾插法创建有头链表(头节点中不存数据,仅指向下一个节点的指针)

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

typedef struct node{
	int data;
	struct node *pNext;
}Node,*pNode;

pNode creatList(pNode pHead){  //尾插法
	int i, len, val;  //len是链表节点数,val是节点data值
	pHead = (pNode)malloc(sizeof(Node));  //给头节点分配空间
	pNode pTail = pHead;  //定义尾节点,初始化在头节点
	pTail->pNext = NULL;  //尾节点的指针为空
	printf("请输入节点个数:");
	scanf("%d", &len);
	for (i = 0; i < len; ++i){
		printf("第 %d 个节点的数值:", i + 1);
		scanf("%d", &val);
		pNode pNew = (pNode)malloc(sizeof(Node));  //为各节点分配空间
		pNew->data = val;
		pTail->pNext = pNew;
		pNew->pNext = NULL;
		pTail = pNew;
	}
	return pHead;
}

void printList(pNode pHead){
	pNode p = pHead->pNext;
	while (NULL != p){
		printf("%d ", p->data);
		p = p->pNext;
	}
	printf("\n");
}

void reverse(struct node* head)//单链表的倒置算法
{
	struct node  *p, *q;
	p = head->pNext;
	head->pNext = NULL;
	while (p)
	{
		q = p->pNext;
		p->pNext = head->pNext;
		head->pNext = p;
		p = q;
	}
}

void findReverse4(pNode pHead){  //找出链表的倒数第四个节点:先反转,再顺序读第四个节点
	reverse(pHead);
	pNode p = pHead->pNext;
	int cnt=1;
	while (NULL != p){
		cnt++;
		p = p->pNext;
		if (cnt < 4)
			continue;
		else if (cnt == 4)
			printf("%d\n", p->data);
	}
	if (cnt <= 4)
		printf("节点数不足4个\n");
}

void findMid(pNode pHead){  //找出链表的中间节点
	pNode p = pHead->pNext;
	int cnt = 0, mid;
	while (NULL != p){
		cnt++;
		p = p->pNext;
	}
	mid = cnt/2;
	
	p = pHead->pNext;
	cnt = 0;
	while (NULL != p){
		if (cnt == mid)
			printf("%d\n", p->data);
		cnt++;
		p = p->pNext;
	}
}

//using step1 and step2 here 使用p、q两个指针,p每次向前走一步,q每次向前走两步,若在某个时候p == q,则存在环。
//if exists a loop, then the pointer which use step2 will catch up with the pointer which uses step1
void has_loop(pNode head){
	pNode p = head;
	pNode q = head;
	while (p != NULL && q != NULL){
		/*
	   p = p->next;
	   (q->next != NULL)
	   q = q->next->next;
	   if (p == q)
	   return 1;
	   */
		//correct it on 17/11/2012
		p = p->pNext;
		q = q->pNext;
		if (q != NULL)
			q = q->pNext;
		if (p != NULL && p == q)
			printf("has loop\n");
	}
	printf("no loop\n");
}

int main(){
	pNode pHead = NULL;
	pHead = creatList(pHead);
	printList(pHead);
	//reverse(pHead);
	//printList(pHead);
	//findReverse4(pHead);
	//findMid(pHead);
	has_loop(pHead);

	system("pause");
	return 0;
}


有头链表与无头链表的区别:

在遍历元素的时候:

有头:

Node *temp;

temp=head->next;        //无头:temp=head;

while(temp!=NULL){

......

temp=temp->next;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值