您的位置:首页 > 其它

带头节点单链表的实现

2015-12-24 21:47 447 查看

心得体会:单链表是一种 链式存取 的数据结构,用一组物理地址任意的存储单元存放线性表中的数据元素。

存储:1.逻辑存储

2.物理存储

思维角度:1.逻辑线性结构 一对一

2.逻辑非线性结构 一对多

实现存储方式:1.连续存储方式 eg:数组的申请 ,用malloc 申请一次申请一整块

2.非连续存储方式 eg :链表,树 等 。每创建一个元素,就申请 一 块空间。

链表的具体存储表示为:

1 用一组任意的存储单元来存放线性表的结点(这组存储单元既可以是连续的,也可以是不连续的)

2 链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息(称为指针(pointer)或链(link))

3 链表通过每个结点的链域将线性表的n个结点按其逻辑顺序链接在一起的。

4 每个结点只有一个链域的链表称为单链表(Single Linked List)。

#include<stdio.h>

#include<stdlib.h>

#include<strings.h>

#include<string.h>

#define TRUE (1)

#define FALSE (0)

typedef unsigned char Boolean;

typedef struct List_Node //结构体的声明

{

int date;

struct List_Node *next;

}List_Node;

typedef List_Node *List_Head; //自定义List_Node * <==> List_Head

List_Head Init_List(void) ; //链表的初始化

void Destroy_List(List_Head *head) ; //链表的销毁

Boolean Push_Frount(List_Head head, int value) ; //头部添加

Boolean Push_Back(List_Head head, int value) ; //尾部添加(

Boolean Pop_Frount(List_Head head) ; //头部删除

Boolean Pop_Back(List_Head head) ; //尾部删除(效率低)

void Show_List(List_Head head) ; //显示链表信息

Boolean Find_Node(List_Head head, int value, List_Node **node) ; //链表的查找

void Sort_List_Ascend(List_Head head) ; //链表升序

void Sort_List_Descend(List_Head head) ; //链表降序

int Get_List_Length(List_Head head) ; //链表的长度

void Modify_Node(List_Head head, int value,int new_value) ; //链表节点的修改

Boolean Insert_Node(List_Head head,int value,int new_value);//插入的新值

static void *Malloc(size_t size); //申请任何类型都可以指向的(size)大小的内存空间

static List_Head Create_Node(void); //申请一个节点

void swap(List_Node *pm ,List_Node *pn,int List_size);

void swap(List_Node *pm ,List_Node *pn,int List_size)

{

List_Head mid =(List_Head) malloc(List_size);

memcpy(mid,pm,List_size);

memcpy(pm,pn,List_size);

memcpy(pn,mid,List_size);

free(mid);

}

List_Head Init_List(void)//链表初始化

{

List_Head head=NULL;

head=Create_Node();

return head;

}

/**************包裹函数*******************/

static void *Malloc(size_t size)//申请任何类型都可以指向的(size)大小的内存空间

{

void *result=malloc(size);

if(result==NULL){ //申请失败的情况下

fprintf(stderr,"the memory is full\n");

exit(1);

}

return result;

}

static List_Head Create_Node(void) //申请一个节点

{

List_Node *node=(List_Node *)Malloc(sizeof(List_Node));

bzero(node,sizeof(List_Node)); //对申请的空间进行清零包括:数据赋0 和 指针赋NULL

return node;

}

void Destroy_List(List_Head *head)//链表的销毁

{

if(head==NULL||*head==NULL){ //传进一个指向链表根指针的指针

return ;

}

List_Node *p=NULL;

List_Node *q=NULL;

p=*head; //p指向head的首地址,

while(p!=NULL){ //p指向的空间的首地址不为空

q=p; //q用于存放p上一次所指的空间的首地址

p=p->next; //进行遍历

free(q); //释放p上一次所指向的空间

}

*head=NULL; //因为根指针的指向没变,但所指向空间内存已释放,故进行赋值为空,避免垃圾数据

}

Boolean Push_Frount(List_Head head, int value)//链表的前添加

{

List_Head new=NULL;

new=Create_Node();

if(head==NULL){

return FALSE;

}

new->date=value; //对插入的数据进行赋值

new->next=head->next;//这两步顺序不能更改,必须先让node->next 先指向head->next

head->next=new; //再让头节点指向新节点

head->date++;

return TRUE;

}

Boolean Push_Back(List_Head head ,int value)//链表的后添加

{

List_Head pm=NULL;

pm=head;

if(head==NULL){ //检验链表是否存在

return FALSE;

}

while(pm->next!=NULL){ //链表遍历条件,最后节点的指针指向是否为NULL

pm=pm->next;

}

pm->next=Create_Node(); //当不满足条件时,循环已经遍历到最后一个节点了

pm->next->date=value;

head->date++;

return TRUE;

}

Boolean Pop_Frount(List_Head head)//链表的前删除

{

if(head==NULL||head->next==NULL){ //判断链表是否存在,且是否有有效的节点

return FALSE;

}

List_Head pm=NULL;

pm=head->next;

head->next=pm->next; //让head->next指向下一个成员的next所指向的位置

free(pm); //依次释放成员空间

head->date--;

return TRUE;

}

Boolean Pop_Back(List_Head head)//链表的后删除

{

if(head==NULL||head->next==NULL){ //链表是否存在以及链表是否存在节点

return FALSE;

}

List_Head pm=NULL; //找到倒数第二个节点

//第二种方法

List_Head pn=NULL; //while(pm->next->next != NULL){

pm=head; //

while(pm!=NULL){ //pm=pm->next;}

//free(pm->next);

pn=pm; //倒数第二个节点

pm = pm->next; //最后一个节点

}

pn->next=NULL; //倒数第二个节点的指针赋NULL,确保不指向其他非法区域

free(pm); //释放最后一个节点的空间

head->date--;

return TRUE;

}

Boolean Insert_Node(List_Head head,int value,int new_value)

{

if(head == NULL){

return FALSE;

}

List_Head node = NULL;

node = Create_Node();

List_Head pm = NULL;

pm = head->next;

while(pm != NULL){

if(pm->date == value){

node->next = pm->next;

pm->next = node;

node->date = new_value;

head->date++;

return TRUE;

}

pm = pm->next;

}

return FALSE;

}

void Show_List(List_Head head)//链表的显示

{

List_Head pm = NULL;

if(head==NULL){ //检验参数是否正确

return ;

}

pm = head->next;

for(pm;pm != NULL;pm=pm->next){

printf(" %d",pm->date); //打印每个节点里的数据

}

printf("\n");

}

Boolean Find_List(List_Head head,int value,List_Node **node)//链表的查找

{

if(head==NULL){

return FALSE;

}

List_Head pm = NULL;

pm = head->next;

while(pm!=NULL){

if(pm->date == value){

if(node != NULL){ //检测欲要指向的节点的指针是否合法

*node = pm; //指向所找到节点的首地址

return TRUE;

}

return FALSE;

}

pm = pm->next; //遍历的步长

}

}

void Sort_List_Ascend(List_Head head)//链表的升序

{

List_Node *p_node = NULL;

List_Node *q_node = NULL;

if(head == NULL || head->date < 2){

return ;

}

for(p_node = head->next; p_node->next ; p_node = p_node->next){

for(q_node = p_node->next; q_node; q_node = q_node->next){

if(p_node->date > q_node->date){

swap(p_node, q_node, sizeof(List_Node) - sizeof(List_Node *));

}

}

}

}

void Sort_List_Descend(List_Head head)//链表的降序

{

List_Node *p_node = NULL;

List_Node *q_node = NULL;

if(head == NULL || head->date < 2){ //不能是空链表,节点必须大于1个

return ;

}

for(p_node = head->next; p_node->next ; p_node = p_node->next){

for(q_node = p_node->next; q_node; q_node = q_node->next){

if(p_node->date < q_node->date){

swap(p_node, q_node, sizeof(List_Node) - sizeof(List_Node *));//交换

}

}

}

}

int Get_List_Length(List_Head head)//链表的长度

{

if(head==NULL){

return -1;

}

return head->date;

}

void Modify_Node(List_Head head ,int value,int new_value)//链表的修改

{

if(head==NULL||head->next==NULL){ //检查参数

return ;

}

List_Head pm = NULL;

pm = head->next; //让指针指向第一个节点

while(pm!=NULL&&pm->date != value){

pm = pm->next;

}

pm->date = new_value;//修改想要的值

}

int main(int argc, char **argv)

{

List_Head head =Init_List(); //链表的初始化

int i = 0;

int insert_next_value =0; //想要插到那个数的后面的那个数

int new_value = 0;

int value = 0;

List_Node *find = NULL;

for(i = 0; i < 10; ++i){ //头部添加10个元素

Push_Frount(head, rand() % 100);

}

printf("显示头部添加的10个元素:\n");

Show_List(head); //显示链表信息

printf("显示尾部输入确定值15:\n");

Push_Back(head,15);

Show_List(head); //显示链表信息

Pop_Frount(head); //头部删除一个

// Pop_Back(head); //尾部删除一个

printf("把原值为15的节点对应的值修改为5:\n");

Modify_Node( head ,15,5);//把原值为15的节点对应的值修改为5

Show_List(head); //显示链表信息

printf("the count of list:%d\n", Get_List_Length(head));// 得到链表的长度

printf("你要找哪个节点:\n");

scanf("%d", &value);

Find_List(head, value, &find);//指向所要找的节点的指针的的地址//

//,所以传进去的参数就是指针的指针

if(find == NULL){

printf("the %d is not found!\n", value);

}else{

printf("found! the value is %d\n", find->date);//找到那个节点的数据

}

printf("降序显示链表的信息:\n");

Sort_List_Descend(head);

Show_List(head); //降序显示链表信息

printf("升序显示链表信息:\n");

Sort_List_Ascend(head);

Show_List(head); //升序显示链表信息

printf("输入想要插入那个数的后面和插入的新值:");

scanf("%d:",&insert_next_value);

printf("请输入插入的新值:");

scanf("%d",&new_value);

Insert_Node(head,insert_next_value,new_value);

Show_List(head);

Destroy_List(&head); //释放空间

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: