利用C指针编写自己的一些数据结构(链表)

30 篇文章 0 订阅

一 链表

自己简单写了一个单链表,记录员工的名字和年龄:

#include<iostream>
#include<stdlib.h>

using namespace std;


typedef struct employee
{
	char name[10];
	unsigned char age;
	struct employee* next;
}Employee,*Employee_p;

Employee_p creat_employee_list(int cnt_number)
{
	Employee_p one;
	one = (Employee*)malloc(sizeof(Employee));
	cin>>one->name;
	cin>>one->age;
	cnt_number = cnt_number - 1;
	if(cnt_number == 0)
		{
			one->next = NULL;
		}
	else
		{
			one->next = creat_employee_list(cnt_number);
		}
	return one;
}

void display_employee_list(Employee_p first_employee)
{
	while(1)
		{
			if(first_employee->next != NULL)
				{
					cout << first_employee->name << endl;
					cout << first_employee->age << endl;
					first_employee = first_employee->next;
				}
			else
				{
					cout << first_employee->name << endl;
					cout << first_employee->age << endl;
					break;
				}	
			
		}

	
}

int main()
{
	Employee_p one_employee;
	one_employee = creat_employee_list(5);
	display_employee_list(one_employee);
	return 0;
}


在创建单链表是,我开始想到的就是利用结构体来完成,在创建过程中使用递归方法完成连接。

在编写时,出了点问题就是在显示链表数据时,总是最后一个现实不了,本来开始while(first_employee->next != NULL)来判断这样最后一个总是显示不了;后来没办法将最后一个利用if/else单独显示。今天和陈铭明交流,发现只要改动循环条件即可:while(first_employee != NULL)就能遍历到最后一个。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

在上面的练习中,在写时一个链表节点就携带一个数据信息,这样没有一种归类的思想,即能不能将要写的所有数据信息用一个结构体表示,然后在链表节点中用一个指针指向携带的数据信息,还有一条链表写好后,关于这条链表我也用一个结构体来指向,表明链表头,链表尾。所以经过修改新的链表出来了:(此次修改中还用到了h文件,用以声明函数和变量)

 

main.cpp

#include<iostream>
#include<stdlib.h>
#include"std_link.h"
using namespace std;

int main()
{
	Linklist* list = (Linklist*)malloc(sizeof(Linklist));
	init_linklist(list);
	add_to_linklist(add_node_employee(),list);
	add_to_linklist(add_node_employee(),list);
	add_to_linklist(add_node_employee(),list);
	display_list(list);
	return 0;
}

void init_linklist(Linklist* linklist)
{
	linklist->head    = NULL;
	linklist->tail    = NULL;
	linklist->current = NULL;
}
Node* add_node_employee(void)
{
	Employee *one_employee = (Employee*)malloc(sizeof(Employee));
	cout<<"please input name and age"<<endl;
	cin>>one_employee->name;
	cin>>one_employee->age;
	Node* one_node = (Node*)malloc(sizeof(Node));
	one_node->info = one_employee;
	one_node->next = NULL;
	return one_node;
}
void add_to_linklist(Node* node,Linklist* list)
{
	if(list->head == NULL)
	{
		list->head = node;
		list->tail = node;
		list->current = node;
	}
	else
	{
		list->tail->next = node;
		list->tail      = node;
		list->current   = node;
	}
}

void display_list(Linklist* list)
{
	Node* first = list->head;
	Employee* employee;
	while(first != NULL)
	{
	    employee = (Employee*)first->info;
		cout<<employee->name<<" "<<employee->age<<endl;
		first = first->next;
	}
}


main.h

#ifndef _STD_LINK_H_
#define _STD_LINK_H_

typedef struct _employee
{
	char name[10];
	unsigned int age;
}Employee;

typedef struct _node
{
	void *info;
	struct _node* next;
}Node;

typedef struct _linklist
{
	Node* head;
	Node* tail;
	Node* current;
}Linklist;
extern void init_linklist(Linklist* linklist);
extern Node* add_node_employee(void);
extern void add_to_linklist(Node* node,Linklist* list);
extern void display_list(Linklist* list);
#endif


运行结果

-----------------------------------------------------------------------------------------------------------------------------------------------------

在上面的基础上又添加查找功能,添加了如下函数:

main.cpp

int compare_employee(Employee* e1,Employee* e2)
{
	return strcmp(e1->name,e2->name);
}
Employee* name_for_seek()
{
	Employee* one_name;
	cout<<"please input name for seeking"<<endl;
	cin>>one_name->name;
	one_name->age = 1;
	return one_name;
}
Node* seek_node(Linklist* list,Employee* name_for_seek,Compare compare)
{
	Node* first = list->head;
	Employee* employee;
	while(first != NULL)
	{
		employee = (Employee*)first->info;
		if(compare(employee->name,name_for_seek->name) == 0)
		{
			cout<<"find the guy"<<endl;
			cout<<"name: "<<employee->name<<"  age: "<<employee->age<<endl;
			return first;
		}
		first = first->next;
		
	}

}

main.h

typedef int (*Compare)(void* ,void* );

但是在调试时出现问题,

在调用完函数Employee* name_for_seek()之后没有返回,这是一个老问题,因为在函数中定义一个结构体是在栈里面的,一旦函数运行完,所分配的栈也就释放了,此时所指向的栈地址是非法的,在linux中应该是非法的。所以将之分配到堆中就可以了。

Employee* name_for_seek()
{
	Employee* one_name = (Employee*)malloc(sizeof(Employee));
	cout<<"please input name for seeking"<<endl;
	cin>>one_name->name;
	one_name->age = 1;
	return one_name;
}

运行结果如下:




 --------------------------------------------------------------------------------------------------------------------------------------------------

然后再添加一个任意delete一个链表元素,刚写完为:

void delete_node(Linklist* list,Employee* name_for_seek)
{
    Node* node_for_delete;
	node_for_delete = seek_node(list,name_for_seek(),(Compare)compare_employee);
	Node* first = list->head;
	Employee* employee;
	if(first == node_for_delete)	
		{
			list->head = first->next;
			cout<<"ok delete the name"<<endl;
		}
	else 
	{
		while(1)
		{
			if(first->next == node_for_delete)
			{
				first->next = node_for_delete->next;
				break;
			}
			else if(first->next == NULL)
			{
				cout<<"sorry delete fail"<<endl;
				break;
			}
			else
				first = first->next;	
		}
	}

}


g++ 编译报错为:

这里面是这样的name_for_seek在参数表中是一个指向Employee的指针,而在seek_node中却作为了函数指针。为了充分学习typedef的函数类型定义,完成了新的程序:

h文件

#ifndef _STD_LINK_H_
#define _STD_LINK_H_

typedef int (*Compare)(void* ,void* );


typedef struct _employee
{
	char name[10];
	unsigned int age;
}Employee;

typedef struct _node
{
	void *info;
	struct _node* next;
}Node;

typedef struct _linklist
{
	Node* head;
	Node* tail;
	Node* current;
}Linklist;
typedef Node* (*Seeknode)(Linklist*,Employee*,Compare);
typedef Employee* (*Nameforseek)(void);


extern void init_linklist(Linklist* linklist);
extern Node* add_node_employee(void);
extern void add_to_linklist(Node* node,Linklist* list);
extern void display_list(Linklist* list);
extern int compare_employee(Employee* e1,Employee* e2);
extern Node* seek_node(Linklist* list,Employee* name_for_seek,Compare compare);
extern Employee* name_for_seek(void);
extern void delete_node(Linklist* list,Seeknode seeknode,Nameforseek nameforseek,Compare compare);
#endif


main文件

#include<iostream>
#include<stdlib.h>
#include"std_link.h"
using namespace std;

int main()
{
	Linklist* list = (Linklist*)malloc(sizeof(Linklist));
	init_linklist(list);
	add_to_linklist(add_node_employee(),list);
	add_to_linklist(add_node_employee(),list);
	add_to_linklist(add_node_employee(),list);
	display_list(list);
	seek_node(list,name_for_seek(),(Compare)compare_employee);
	delete_node(list,(Seeknode)seek_node,(Nameforseek)name_for_seek,(Compare)compare_employee);
	display_list(list);
	return 0;
}

void init_linklist(Linklist* linklist)
{
	linklist->head    = NULL;
	linklist->tail    = NULL;
	linklist->current = NULL;
}
Node* add_node_employee(void)
{
	Employee *one_employee = (Employee*)malloc(sizeof(Employee));
	cout<<"please input name and age"<<endl;
	cin>>one_employee->name;
	cin>>one_employee->age;
	Node* one_node = (Node*)malloc(sizeof(Node));
	one_node->info = one_employee;
	one_node->next = NULL;
	return one_node;
}
void add_to_linklist(Node* node,Linklist* list)
{
	if(list->head == NULL)
	{
		list->head = node;
		list->tail = node;
		list->current = node;
	}
	else
	{
		list->tail->next = node;
		list->tail      = node;
		list->current   = node;
	}
}

void display_list(Linklist* list)
{
	Node* first = list->head;
	Employee* employee;
	cout<<"display all list "<<endl;
	while(first != NULL)
	{
	    employee = (Employee*)first->info;
		cout<<employee->name<<" "<<employee->age<<endl;
		first = first->next;
	}
}
int compare_employee(Employee* e1,Employee* e2)
{
	return strcmp(e1->name,e2->name);
}
Employee* name_for_seek(void)
{
	Employee* one_name = (Employee*)malloc(sizeof(Employee));
	cout<<"please input name for seeking"<<endl;
	cin>>one_name->name;
	one_name->age = 1;
	return one_name;
}
Node* seek_node(Linklist* list,Employee* name_for_seek,Compare compare)
{
	Node* first = list->head;
	Employee* employee;
	while(first != NULL)
	{
		employee = (Employee*)first->info;
		if(compare(employee->name,name_for_seek->name) == 0)
		{
			cout<<"find the guy"<<endl;
			cout<<"name: "<<employee->name<<"  age: "<<employee->age<<endl;
			return first;
		}
		first = first->next;
		
	}
	cout<<"sorry AI can not find your name"<<endl;

}

void delete_node(Linklist* list,Seeknode seeknode,Nameforseek nameforseek,Compare compare)
{
    Node* node_for_delete;
	cout<<"delete one name:"<<endl;
	node_for_delete = seeknode(list,nameforseek(),compare);
	Node* first = list->head;
	
	if(first == node_for_delete)	
		{
			list->head = first->next;
			cout<<"ok delete the name"<<endl;
		}
	else 
	{
		while(1)
		{
			if(first->next == node_for_delete)
			{
				first->next = node_for_delete->next;
				break;
			}
			else if(first->next == NULL)
			{
				cout<<"sorry delete fail"<<endl;
				break;
			}
			else
				first = first->next;	
		}
	}

}

在编写上面时遇到了一些基本错误:

typedef Node* (*Seeknode)(Linklist*,Employee*,Compare);
typedef Employee* (*Nameforseek)(void);
typedef int (*Compare)(void* ,void* );

类似于这样的定义顺序,这是编译不懂过的,当然十年后可能通过。

还有一个问题就是,看了代码会发现,我错误的认为,只有main函数可以直接调用其他函数,而其他函数之间的调用必须通过参数传递,不是的,只要函数的使用范围允许即可(有机会会再研究这个问题),简化程序如下:

void delete_node(Linklist* list)//Seeknode seeknode,Nameforseek nameforseek,Compare compare)
{
    Node* node_for_delete;
	cout<<"delete one name:"<<endl;
	node_for_delete = seek_node(list,name_for_seek(),(Compare)compare_employee);
	Node* first = list->head;
	if(first == node_for_delete)	
		{
			list->head = first->next;
			cout<<"ok delete the name"<<endl;
		}
	else 
	{
		while(1)
		{
			if(first->next == node_for_delete)
			{
				first->next = node_for_delete->next;
				break;
			}
			else if(first->next == NULL)
			{
				cout<<"sorry delete fail"<<endl;
				break;
			}
			else
				first = first->next;	
		}
	}

}


运行结果:

(有机会再补充)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值