一个小白的C语言学习成长
第一次写博客,也是一个小白,非计算机专业的小白,想通过一个平台慢慢提高自己,慢慢记录自己的成长,也希望CSDN社区的小伙伴们能够宽容我这样的小白,有什么不对的地方希望各位能见谅。
C语言实现链表的操作
用C语言首先构建链表的一系列的操作,其中包括链表的生成,链表的排序,链表的倒序,改变两两节点指向,头插法,尾插法等基本操作。直接上代码。代码中有详细的注解
#include <stdio.h>
#include<stdlib.h>
#if 0
头插法
1.让新来的节点,有所指向,新来的节点不会打断原有的指向关系
尾插法
#endif
#if 0
void test()
{
Node a,b,c,d;
a.data=1;
b.data=2;
c.data=3;
d.data=4;
Node *head=&a;
a.next=&b;
b.next=&c;
c.next=&d;
d.next=NULL;
Node *p =head;
while (p) {
printf("%d\n",p->data);
p=p->next;
}
Node *p1=head;
Node *p2 =p1->next;
Node *p3;
while (p2) {
p3=p2->next;
p2->next=p1;
p1=p2;
p2=p3;
}
head->next=NULL;
while (p1) {
printf("%d\n",p1->data);
p1=p1->next;
}
}
#endif
typedef struct Link
{
int data;
struct Node * next;
}Node;
//创建一个空链表
Node * createLink()
{
Node *head = (Node*)malloc(sizeof(Node));
head->next=NULL;
return head;
}
//头插法创建链表
Node * addHeadLink(Node*head)
{
for (int i=0;i<10;i++)
{
Node *cur=(Node*)malloc(sizeof(Node));
cur->data=rand()%100;
cur->next=head->next;
head->next=cur;
}
return head;
}
//判断一个链表的长度
int lenLink(Node *head)
{
int len = 0;
Node *p=head->next;
while (p) {
len+=1;
p=p->next;
}
return len ;
}
//尾插法添加链表元素
Node * addEndLink(Node*head)
{
Node *p = head;
for(int i=0;i<10;i++)
{
Node *cur =(Node*)malloc(sizeof(Node));
cur->data=rand()%80;
cur->next=NULL;
p->next=cur;
p=p->next;
}
return head;
}
//指定位置插入链表元素
Node * addLink(Node*head,int n,int m)
{
Node *cur =head;
int num=0;
while(num!=n-1)
{
cur=cur->next;
num++;
}
Node *q=(Node*)malloc(sizeof(Node));
q->data=m;
q->next=cur->next;
cur->next=q;
return head;
}
//排序该表值法
void sortPopLink(Node *head,int len)
{
for(int i=0; i<len-1; i++)
{
Node * r = head->next;
for (int j=0;j<len-1-i;j++)
{
Node * p=r->next;
if(r->data>p->data)
{
r->data=r->data^p->data;
p->data=r->data^p->data;
r->data=r->data^p->data;
}
r=r->next;
}
}
}
//排序改变地址法
void sortPopAdressLink(Node*head,int len)
{
for (int i=0;i<len-1;i++)
{
Node *cur =head;
Node *p = cur->next;
Node *q =p->next;
for (int j=0;j<len-1-i;j++)
{
if(p->data>q->data)
{
cur->next=p->next;
p->next=q->next;
q->next=p;
Node *temp =p;//改变P和q的次序非常重要。第一次改变之后为cur->q->p;所以需要改变次序
p=q;
q=temp;
}
cur=cur->next;
p=p->next;
q=q->next;
}
}
}
//倒序eg 5->4->3->2->1->NULL NULL->1->2->3->4->5
Node * inverseLink(Node *head)
{
Node *p = head->next,*q;//先定义一个指针q存储
head->next = NULL;//打断整个链表。创建一个空链表
while(p != NULL)
{
q = p->next;//q先记录p的下一个节点
p->next = head->next;//头插法(先来的节点有所指向,指向head->next)
head->next = p; //头部节点指向新来的节点
p = q; //节点向后移位
}
return head;
}
//两两交换eg 5->4->3->2->1->NULL 4->5->2->3->1->NULL
Node *changeTwoLink(Node*head)
{
Node *cur = head;
Node *m=cur->next;
while (((cur!=NULL)&&(cur->next!=NULL))&&(m->next!=NULL))
{
Node* node1 = cur->next; //指针移动
Node* node2 = node1->next;
Node* rear = node2->next;
cur->next = node2; //指针交换
node2->next = node1;
node1->next = rear;
cur = node1;
m=cur->next;
}
return head;
}
//查找指定元素的地址
char * findLink(Node*head,int data)
{
Node *p=head->next;
while (p)
{
if(p->data==data)
{
break;
}
p=p->next;
}
return p;
}
//删除指定元素
void deleteLink(Node*head,int n)
{
Node*p=head->next;
int m=1;
while (m!=n-1) {
p=p->next;
m++;
}
Node *q=p->next;
p->next=q->next;
free(q);
}
//把所有的链表元素输出
void printLink(Node*head)
{
Node *p=head->next;
while (p) {
printf("%d\n",p->data);
p=p->next;
}
}
//释放链表
void releaseLink(Node *head)
{
Node * p;
while(head)
{
p = head->next;
free(head);
head = p;
}
printf("the link have been released!\n");
}
int main()
{
Node *head = createLink();
head = addEndLink(head);
printLink(head);
int len =lenLink(head);
printf("the length of link is %d\n",len);
sortPopAdressLink(head,len);
printf("after pop sort\n");
printLink(head);
addLink(head,2,10);
printf("====================\n");
printLink(head);
printf("=========inverse========\n");
inverseLink(head);
printLink(head);
printf("=========change========\n");
changeTwoLink(head);
printLink(head);
printf("adress = %p\n",findLink(head,78));
deleteLink(head,3);
printf("===============after delete======\n");
printLink(head);
releaseLink(head);
return 0;
}
链表操作的几个小结
1.采用头插法构建链表记住:让新来的节点有所指向,头节点下一个节点指向新来的节点。即cur->next = head->next;head->next = cur;
2.链表反转的核心思想:先把头节点打断,让头节点指向NULL,然后用头插法的原则将元素一个个往头部插入,如此一来第一个节点就到最后的节点,即让链表反转。
3.mallco从堆上申请空间后一定记住释放,遵守先申请后释放,后申请先释放的原则,类似栈原理。