C语言单向链表基本操作

数据结构练习

“`
typedef
struct node{
int data;
struct node * next;
} Node;

void Create(Node**);
void Output(Node*);
Node* GetPtr(Node*,int);
void Insert(Node**);
void Delete(Node**);
int Traverse(Node*);
Node* Reverse(Node*);

int main(void)
{
int pos;
Node* head=NULL;
printf(“执行创建链表操作\n”);
Create(&head);
GetPtr(head,pos);
printf(“执行插入操作\n”);
Insert(&head);
Output(head);
printf(“执行删除操作\n”);
Delete(&head);
Output(head);
Traverse(head);
printf(“执行倒置操作\n”);
head=Reverse(head);
Output(head);
return 0;
}

//创建链表有两种方法:1.头插法 2.尾插法

//这里先简单示范第一种插法(头插法比较简单,但插入和输出的顺序是相反的,不符合平时的思维)
//比如你输入1 2 3,输出的结果会是3 2 1

//这里Init的返回值有两种形式

/* 1.void 那就需要使用指针的指针,这是为什么呢?
很简单,你是想要改变head的值使他重新指向新的地址,大家都知道如果你要想改变主函数的变量的值,
那就必须得传指针,而又考虑到head本身就是一个指针,为了改变它的值,就传指针,就出现了指针的指针
如果不传指针的话,你在非main函数做的任何操作都与main函数中的变量无关
如果这里想不通,可以直接问我;

/*
2.Node* 就是将改变后的 head,直接赋值给主函数的head(写这种形式,就说明你对指针没有了解);
*/

/*
void Create(Node**p_head)
{
// Node *p=malloc(sizeof(Node));在这里我犯了一个错误(应该是同名变量的错误);
int key;
printf(“请输入你要插入的值(输入零即停止)\n”);
scanf(“%d”,&key);
while(key)
{
Node *p=malloc(sizeof(Node));
p->data=key;
p->next=*p_head;
*p_head=p;
scanf(“%d”,&key);
}
}
*/

//这是尾插法
//尾插法符合平常思维特点如你输入(1 2 3 4)
//对应的输出就是1 2 3 4而头插法是完全相反的(所以在这里我以尾插法为例);

void Create(Node**p_head)
{
printf(“请输入你要插入的值(输入零即停止)\n”);
int key;
scanf(“%d”,&key);
Node *last = NULL;

while( key )
{
 Node *p = malloc(sizeof(Node));
 p -> data = key;

 if(* p_head == NULL)
 {
   p->next = *p_head;
  * p_head = p;
   last = p;    
 }
 else
 {
    last -> next = p;
    p -> next = NULL;
    last = p;
 }
 scanf("%d",& key); 
}

}

//倒置操作也是很简单总体思想就是先将头结点去掉,然后搭建一个新的链表;
// 当然这里返回类型也可以是void类型但要求使用指针的指针

Node* Reverse(Node*head)
{
if(Traverse(head)<=1)
{
return head;
}
else{
Node * leftptr = head;
Node * currentptr = leftptr->next;
Node * rightptr=NULL;
leftptr -> next = NULL;
while(currentptr)
{
rightptr=currentptr->next;
currentptr->next=leftptr;
leftptr=currentptr;
currentptr=rightptr;
}
return leftptr;
}
}

Node* GetPtr(Node*head,int pos)//如果pos是1则返回值就是第二个节点,但以下标从零开始就是下标为 1;
{
Node *p = head;
if(pos == 0 || p == NULL)
{
return head;
}
int i;
for(i = 0;p && i < pos;i ++)
{
p = p -> next;
}
return p;
}

//这里是插入操作,很明显你需啊考虑特殊情况,就是如果他要插头结点怎么办?
//这也很好解决,就是使用头插法
//注意这里使用的也是指针的指针,这也为特殊情况做准备,因为,一旦要插头结点
// 很明显head的要改变,如果要改变,就得要传指针,而head本身就是指针,如果你想改变指针的值,就得传指针的指针;
//总的来说是这三个步骤
//1.定义一个新结点 2.对新结点赋值 3.连接新结点

void Insert(Node**p_head)
{
printf(“请输入你要插入的位置,和要插入的值:”);
int pos,key;
scanf(“%d%d”,&pos,&key);
Node * p = malloc ( sizeof ( Node ));
Node * ptr = NULL;
p -> data = key;

if(pos == 0)
{
p -> next = * p_head ;
* p_head = p ;
}else{
ptr = GetPtr(* p_head,pos-1);
p -> next= ptr -> next;
ptr -> next = p;
}
}

//删除操作,也是很简单,其原理就是先添加一个节点,然后,让这个节点被赋值为指向他上一个节点指向的位置
//使这个节点的地址与原结点相同,最后同free它的地址从而去掉它的内存
//总得来说就四个步骤: 1.定义新结点 2.对新结点赋值 3.连接新链表 4.free掉它的内存

void Delete(Node ** p_head)//这里是按照数组下标原则删除
{
Node * ptr = malloc ( sizeof (Node) ) ;
printf(“请输入你要删除元素的位置:”);
int pos ;
scanf(“%d”,& pos) ;
Node * p = NULL;
if(pos == 0)
{
p = *p_head;
* p_head = (* p_head ) -> next;
free( p );
}else{
p = GetPtr( * p_head,pos - 1);
ptr = p -> next;
p -> next= ptr -> next;
free( ptr );
}

}

int Traverse(Node*head)
{
Node * p = head;
int count=0;
while( p )
{
p=p->next;
count++;
}
return count;
}

void Output(Node*head)
{
Node * p = malloc ( sizeof ( Node ) );
p = head ;
while( p )
{
printf(“%d “,p -> data);
p = p-> next;
}
putchar(‘\n’);
}`

总结:单向链表是链表中最简单,也是最重要的,如果那里有问题,欢迎提问.“

猜你喜欢

转载自blog.csdn.net/weixin_40867255/article/details/82666661