带头节点单链表的实现
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;
}
心得体会:单链表是一种 链式存取 的数据结构,用一组物理地址任意的存储单元存放线性表中的数据元素。
存储: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;
}
相关文章推荐
- Cracking code interviews_1
- 黑马程序员--C语言自学笔记---13结构体、预编译、宏、条件编译
- 利用OpenCV的人脸检测给头像带上圣诞帽
- HDU 2093 考试排名
- Android 人名 随机抽奖
- JavaScript:理解worker事件api
- data-ng-hide 指令
- Mysql 关联查询得where条件
- POJ1035——Spell checker
- Android-Creating an Input Method(IME)
- Overrall Perspective
- 游戏框架之UI管理(二)
- 程序员常见面试之 数据库 知识点小结(二)
- serialVersionUID的作用
- 葡萄城报表-核心代码展示
- JDK,JRE,JVM,SDK,API,ADT,OOM,ANR
- 把相片的详情列表里显示的时间与文件名和标题里指示的时间统一
- Codeforces 607B - Zuma (区间DP)
- Errors running builder 'DeploymentBuilder' on project '工程名' xxxNullpointException
- 葡萄城报表-核心代码展示