学习数据结构已经很久了,现在复习一下,欢迎各位批评指正
本文主要是实现单链表的建立/测长/排序/插入/删除功能,首先定义结构体如下:
typedef struct student
{
int data;
struct student *next;
}node;
单链表的建立
node *create()
{
node *head,*p,*s;
int x,cycle=1;
head=(node *)malloc(sizeof(node));
p=head;
printf(" please input the data:\n");
while(cycle)
{
scanf("%d",&x);
if(x!=0)
{
s=(node *)malloc(sizeof(node));
s->data=x;
p->next=s;
p=s;
}
else
{
cycle=0;
}
}
head=head->next;
p->next=NULL;
return(head);
}
注意我这里是以0为输入结束标志,你们可以进行改动
单链表的测长
int length(node *head)
{
int num=0;
node *p;
p=head;
while(p)
{
num++;
p=p->next;
}
return num;
}
单链表的排序
使用冒泡排序算法进行升序排序;冒泡排序就是依次比较两个相邻的数,将小数放前面,大的放后面。
- 在第一趟:首先第1个数和第2个数,小的放前,大的放后。然后比较第2个和第3个数,小的放前,大的放后。如此继续,直到比较最后两个数。第一趟结束,将最大的数放到了最后面
- 第二趟:仍从第一对数进行比较,小的放前,大的放后,直到比较到倒数第二个数(倒数第一的位置上已经是最大的)。第二趟结束,将第二大的数放在了倒数第二的位置上。
- 总共经过n-1趟,完成排序。因为当只有一个元素时,该元素一定是最小的。
node *sort(node *head)
{
node *p;
int n;
n=length(head);
int temp;
if(head==NULL||head->next==NULL)
{
return head;
}
for(int j=1;j<n;j++)
{
p=head;
for(int i=0;i<n-j;i++)
{
if(p->data>p->next->data)
{
temp=p->data;
p->data=p->next->data;
p->next->data=temp;
}
p=p->next;
}
}
return head;
}
单链表的插入
单链表的插入有三种情况:
- 插入在头结点之前,即p1的前面
此时进行的操作是 p0->next=p1; head=p0; - 插入中间结点,即将p0插入到p2与p1的中间
此时进行的操作是 p0->next=p1;p2->next=p0;(这里不能调换顺序) - 插入尾结点,即p1的后面
此时进行的操作是 p0->next=NULL;p1->next=p0;
node *insert(node *head,int num) //按序插入
{
node *p0,*p1,*p2;
p1=head;
p0=(node *)malloc(sizeof(node));
p0->data=num;
while(p0->data>p1->data&&p1->next!=NULL)
{
p2=p1;
p1=p1->next;
}
if(p0->data<=p1->data)
{
if(head==p1) //情况1
{
p0->next=p1;
head=p0;
}
else //情况2
{
p0->next=p1;
p2->next=p0;
}
}
else //情况3
{
p0->next=NULL;
p1->next=p0;
}
return head;
}
单链表的删除
单链表的删除有两种情况:
- 删除头结点,即p1
此时进行的操作为:head=p1->next;free(p1); - 删除中间结点(包含尾结点),即p1
此时进行的操作为:p2->next=p1->next;free(p1);
node *del(node *head,int num) //删除元素num
{
node *p1,*p2;
p1=head;
while(num!=p1->data&&p1->next!=NULL)
{
p2=p1;
p1=p1->next;
}
if(num==p1->data)
{
if(p1==head) //情况1
{
head=p1->next;
free(p1);
}
else //情况2
{
p2->next=p1->next;
free(p1);
}
}
else
{
printf("\n %d could not been found",num);
}
return head;
}
单链表的打印
void print(node *head)
{
node *p;
int n;
n=length(head);
printf("\nNow,these %d records are:\n",n);
p=head;
while(p)
{
printf("%d\n",p->data);
p=p->next;
}
}
单链表的逆置
例如:在第一次逆置中,将p1跟p2之间的方向进行逆转
执行的操作是 p3=p2->next; p2->next=p1; p1=p2;p2=p3;
其中p3用来记录p2后面的元素;p2->next=p1实现p2跟p1逆置;如下所示
p1=p2;p2=p3;是选择下一次进行逆置的指针,此时状态如下
如此下去,最终p1指向最后一个元素,p2=NULL;此时只需执行操作head->next=NULL;head=p1;
node *reverse(node *head)
{
node *p1, *p2, *p3;
if(NULL==head||NULL==head->next) //当链表为空或者只有一个元素时
{
return head;
}
p1=head;
p2=p1->next;
while(p2) //每相邻的两个元素进行逆置
{
p3=p2->next;
p2->next=p1;
p1=p2;
p2=p3;
}
head->next=NULL;
head=p1;
return head;
}
头文件
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<conio.h> //声明控制台输入输出所需函数的头文件
using namespace std;
主函数
int main()
{
node *head;
int len;
head=create();
len=length(head);
printf("the number of records is: %d",len);
printf("\n排序后:\n");
head=sort(head);
print(head);
printf("删除元素3后:\n");
head=del(head,3);
print(head);
printf("插入元素5后:\n");
head=insert(head,5);
print(head);
printf("进行逆置后:\n");
head=reverse(head);
print(head);
return 0;
}