您的位置:首页 > 其它

单链表实现

2016-05-12 23:29 330 查看
单链表:1、逻辑上连续,位置上可以不连续的存储方式。

2、单链表由无数个结点组成,每个结点由数据段和指针域组成,数据段存储数据,指针域存储后继的地址。

3、每个结点最多有一个前继和一个后继。

4、其中第一个结点没有前继,所以我们通常建立一个头结点来保存他的位置,其中头结点的数据段我们不关注。

5、最后一个结点没有后继,所以我们将最后一个结点的指针域赋为NULL.
//函数声明:"linklist.h"

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
typedef struct linknode
{
ElemType data;
struct linknode *next;
}node;
void judgement_memory(node * p);                //判断动态内存是否开辟成功

node* creat_order();                //正向建立链表,尾插法
node * creat_reverse();             //反向建立链表,头插法

void insert(node *head, int i, ElemType x);     //在i位置上插入值为x的结点

void delete_place(node *head, int i);           //删除i结点
int delete_element(node *head, ElemType const x);       //删除第一个值为x的结点
void delete_all_element(node *ret, ElemType x);       //删除所有值为x的结点

void find_element(node *head, ElemType const x);     //寻找所有值为x的结点位置
void find_place(node *head, int i);                  //寻找i结点上的元素

void length_list(node *head);

void output(node *head);                              //打印链表

node* inits_linklist(node *head);                  //释放链表

void sortrank(node *head);                      //对链表进行排序

int means();

//函数实现:"linklist.c"

#include"linklist.h"
void judgement_memory(node * p)     //判断开辟内存是否成功
{
if (NULL == p)
{
perror("out of memory:");
exit(EXIT_FAILURE);
}
}

node* creat_order()                    //建立一个具有头结点单链表,顺序插入(尾插法)
{
printf("开始建立:");
node *head, *p, *r;
int x = 0;
head = (node *)malloc(sizeof(node));             //建立头结点
judgement_memory(head);
r = head;
while (1)
{
scanf("%d", &x);
if (x != 0)                                        //以0作为链表结束标志
{
p = (node *)malloc(sizeof(node));
judgement_memory(p);
p->data = x;
r->next = p;
r = p;
}
else
break;
}
r->next = NULL;
printf("创建成功\n");
return head;
}

node * creat_reverse()           //建立一个具有头结点的单链表,逆序输入(头插法)
{
printf("开始建立:");
node *head, *p, *r, *q;
int x = 0;
head = (node *)malloc(sizeof(node));
judgement_memory(head);
p = (node *)malloc(sizeof(node));                  //开辟最后一个结点
judgement_memory(p);
p->next = NULL;
scanf("%d", &x);
p->data = x; 
r = head;
q = p;
r->next = q;
while (1)
{
scanf("%d", &x);
if (x!= 0)
{
p = (node *)malloc(sizeof(node));
judgement_memory(p);
p->data = x;
r->next = p;
p->next = q;
q = p;
}
else
break;
}
printf("创建成功\n");
return head;
}

void insert(node *head, int i, ElemType x)                 //插入一个结点
{
node *r;
node *s = (node *)malloc(sizeof(node));
judgement_memory(s);
s->data = x;
while (NULL != head&&i>1)    //要在第i个结点上插入,则先找到第i-1个结点
{
i--;
head = head->next;
}
if (NULL != head&&i!=0)              //判断是不是头结点和结点是否存在
{
r = head->next;
head->next = s;
s->next = r;
printf("插入成功\n");
}
else
printf("结点不存在\n");
}

void delete_place(node *head, int i)                 //删除链表中一个指定位置的结点
{
node *p;
if (NULL == head)                                 
{
printf("链表下溢\n");
}
else
{
while (NULL != head&&i>1)            //找到第i-1个结点
{
i--;
head = head->next;
}
if (NULL == head||i==0)
printf("没有该位置\n");
else
{
p = head->next;
head->next = p->next;
free(p);
p = NULL;
printf("删除成功\n");
}
 }
}

int delete_element(node *head, ElemType const x)   //删除链表中一个指定的x元素
{
node *p, *q;
if (head == NULL)                              //链表下溢,-1
return -1;
if (x == head->data)                           //判断第一个结点的数据是不是x
{
p = head;
head = head->next;                          
free(p);
p = NULL;
return 0;
}
else
{
while (NULL != head&&head->data != x)         //在链表剩下的元素中寻找x
{
q = head;
head = head->next;
}
if (NULL == head)                              //没找到返回 0
return 0;
else
{
p = head;
q->next = p->next;
free(p);
p = NULL;
}
}
return 1;                                            //删除成功返回1
}
void delete_all_element(node *ret, ElemType x)       //根据元素删除,将这个链表里面的这个元素的结点全部删除
{
int m = 0;
int count = 0;
while (1)
{
m = delete_element(ret, x);
if (m == 0 || m == -1)
break;
count++;
}
if (m == 0)
{
if (count == 0)
printf("没有此元素\n");
else
printf("删除成功\n");
}
else
printf("链表下溢\n");
}

void find_element(node *head, ElemType const x)         //通过元素查找链表中该元素的位置找到返回结点
{
head = head->next;                 //head是头结点,head->next指向下一个结点
int count = 0;
int i = 0;
while (head)
{
count++;
if (head->data == x)                            //如果找到输出count
{
i++;
printf("元素位置:%d\n", count);
}
head = head->next;
}
if (i == 0)                         //如果没有输出count,说明没有x,所以i==0;
printf("查询无果\n");
else
printf("\n");
}

void find_place(node *head, int i)              //通过位置来查找该链表中位于此位置的元素
{
head = head->next;
while (i>1)
{                               //如果要找第i个结点的元素,则要先找到第i-1个结点
i--;
head = head->next;
if (head->next == NULL)
break;
}
if (i == 1)
printf("结点元素:%d\n", head->data);
else
printf("查询无果\n");
}

void length_list(node *head)           //求链表长度
{
head = head->next;
int count = 0;
while (head)
{
count++;
head = head->next;
}
printf("链表长度:%d\n", count);
}

void output(node *head)                          //打印链表
{
head = head->next;                            //让头结点指向下一个结点
printf("输出链表:");
while (head != NULL)
{
printf("%d  ", head->data);
head = head->next;
}
printf("\n");
}

node* inits_linklist(node *head)    //初始化链表
{
node *p,*r;
p = head;
while (p != NULL)
{
r = p;
p = p->next;
free(r);
r = NULL;
}
head = NULL;
p = NULL;
printf("初始化成功\n");
return head;
}

void sortrank(node *head)                                  //对链表进行排序
{
node *p, *r;
p = head->next;
ElemType tmp;
while (p != NULL)
{
r = head->next;
while (r->next != NULL)
{
if ((r->data) > (r->next->data))
{
tmp = r->data;
r->data = r->next->data;
r->next->data = tmp;
}
r = r->next;
}
p = p->next;
}
printf("排序成功\n");
}

int means()                                     //选择方式
{
int means = 0;
while (1)
{
printf("请选择的方式:");
scanf("%d", &means);
if (means == 1 || means == 2)
break;
else
printf("选择无效,请重新输入\n");
}
return means;
}

//函数测试:

#include"linklist.h"

int main()
{
printf("*****************************************\n");
printf("*****************************************\n");
printf("**1.Creat_LinkList    2.Insert_Element **\n");
printf("**3.Find              4.Delete_Element **\n");
printf("**5.Length_LinkList   6.Output_LinkList**\n");
printf("*7.InitsLinkLinst     8.Sortrank       **\n");
printf("*0.Exit               *******************\n\n\n");

node *ret=NULL;
ElemType x;
int i=0;
int n = 0;
while (1)                                      //循环起来,直到选择0结束
{
printf("请选择功能:");
scanf("%d", &n);
if (n == 0)
{
free(ret);
exit(1);
}
if (n == 1 && ret == NULL)
{                                        //选择正序建立链表还是逆序建立链表,并且链表以0作为结束标志
printf("**1.creat_order  2.creat_reverse **\n");
if (means() == 1)
ret = creat_order();
else
ret = creat_reverse();
}
else if (n != 1&& ret == NULL)         //必须先建立链表,才能进行其他操作
printf("请建立链表\n");
else if (ret!=NULL&&n!=1)
{
switch (n)
{
case 2:
printf("请输入要插入的位置和要插入的元素\n");
scanf("%d", &i);
scanf("%d", &x);
insert(ret, i, x);
break;
case 3:                        //选择根据位置查找还是根据元素查找
{
 printf("**1.find_place         2.find_element **\n");
 if (means() == 1)
 {
 printf("请输入要查找的位置:");
 scanf("%d", &i);
     find_place(ret, i);
 }
 else
 {
    printf("请输入要查找的元素:");
scanf("%d", &x);
    find_element(ret, x);
}
 }
break;
case 4:           //选择根据位置删除还是根据元素删除                   
{
printf("**1.delete_place     2.delete_element **\n");    
if (means() == 1)
{
printf("请输入要删除的位置:");
scanf("%d", &i);
delete_place(ret, i);
}
else                                 
{
printf("请输入要删除的元素:");
scanf("%d", &x);
delete_all_element(ret, x);              //根据元素删除,将这个链表里面的这个元素的结点全部删除
}
}
break;
case 5:
length_list(ret);
break;
case 6:                           //打印链表
output(ret);
break;
case 7:                           //初始化链表,将链表制为空
ret = inits_linklist(ret);
break;
case 8:
sortrank(ret);
break;
default:
printf("选择无效,请重新选择\n");
break;
}
}
 
}
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: