这段时间主要学习了c语言高级知识,和数据结构的部分。在学习完c语言指针函数等知识过后,进行了数据结构部分的学习,数据结构主要学习了链表,栈结构,队列,树和二叉树,哈希表,和一下排序算法。
其中数据结构中的链表部分最为重要,链表是一种可以利用零散空间的数据结构,它利用一个next指针指向下一个节点,我们可以利用这一点进行链表的创建,修改,增减,删除等操作
栈这种数据结构在日常使用的并不多,主要用于系统中,一个栈有栈顶和栈底,数据只可以从栈顶进,栈顶出,所以满足先进后出原则
队列的特点
特点:先进先出, 后进后出
实现: 顺序结构 链式结构
概念: 队头 队尾
ps: 不允许在中间做插入或者删除的操作
二叉树带有一个左孩子和一个右孩子,我们学习了先序遍历,中序遍历,和后序遍历
不带头结点的单链表创建
//创建新的节点
struct node* create_node()
{
struct node *pnew = NULL;
pnew = (struct node*)malloc(sizeof(struct node));
if(NULL == pnew)
{
printf("malloc error!%s, %d\n", __FILE__,__LINE__);
exit(-1);
}
pnew->next = NULL;
return pnew;
}
//尾插法创建链表
struct node* create_list()
{
struct node *head = NULL; //头指针:保存第一个节点的地址
struct node *pnew = NULL; //保存新的节点地址
struct node *tail = NULL; //标记最后一个节点的地址
int x;
scanf("%d", &x);
while(getchar()!='\n');
while(x)
{
//1、创建新的节点,并赋值
pnew = (struct node*)malloc(sizeof(struct node));
if(NULL == pnew)
{
printf("malloc error, %s, %d\n",__FILE__,__LINE__);
break;
}
pnew->data = x;
pnew->next = NULL;
//2、加入链表
if(NULL == head)
{
head = pnew;
tail = pnew;
}
else
{
tail->next = pnew;
tail = pnew;
}
scanf("%d", &x);
while(getchar()!='\n');
}
return head;
}
不带头结点的单链表删除
//ps:删除操作重点考虑: 头删和其他位置
void list_del_by_index(struct node **phead, int index)
{
//入参检查
if(phead == NULL)
{
return ;
}
if(*phead == NULL)
{
return ;
}
int len = list_len(*phead);
if(index<1 || index>len)
{
return ;
}
//正确流程
#if 0
(1)保存删除节点地址
(2)将删除节点从链表中移除
(3)释放内存
#endif
struct node *pdel = NULL;
if(1 == index)
{
pdel = *phead;
*phead = (*phead)->next;
free(pdel);
}
else
{
struct node *psearch = list_search_by_index(*phead, index-1);
pdel = psearch->next;
psearch->next = pdel->next;
free(pdel);
}
return ;
}
不带头结点的单链表升序
//(1)从旧链表中找出最大值
struct node*find_max_from_oldlist(struct node*head)
{
struct node *pmax = head;
struct node *p = head;
while(p!=NULL)
{
if(p->data > pmax->data)
{
pmax = p;
}
p = p->next;
}
return pmax;
}
//(2)将最大值从旧链表中移下来
struct node* remove_max_from_oldlist(struct node*head, struct node*pmax)
{
if(pmax == head)
{
head = head->next;
}
else
{
struct node *p = head;
while(p->next != pmax)
{
p = p->next;
}
p->next = pmax->next;
}
pmax->next = NULL;
return head;
}
//(3)将最大值通过头插法加入新的链表
struct node* add_newlist(struct node*head, struct node *pmax)
{
pmax->next = head;
head = pmax;
return head;
}
//链表的升序排序
struct node*list_sort(struct node *head)
{
struct node *new_head = NULL;
struct node *pmax = NULL;
while(head!=NULL)
{
//(1)从旧链表中找出最大值
pmax = find_max_from_oldlist(head);
//(2)将最大值从旧链表中移下来
head = remove_max_from_oldlist(head, pmax);
//(3)将最大值通过头插法加入新的链表
new_head = add_newlist(new_head, pmax);
}
return new_head;
}
带头结点的链表最重要的就是创建一个头结点,保存链表的基本信息,在这个头结点的后面进行,增删改查等操作
带头结点的链表添加
//头插法创建链表
void create_list(struct node *head)
{
struct node *pnew = NULL;
char ch;
printf("是否创建链表?");
scanf("%c", &ch);
while(getchar()!='\n');
while(ch == 'y' || ch== 'Y')
{
//1、创建新的节点,并赋值
pnew = create_node();
printf("请输入学号:");
scanf("%d", &pnew->num);
while(getchar()!='\n');
printf("请输入姓名:");
scanf("%s", pnew->name);
while(getchar()!='\n');
//2、加入链表
#if 0
if(head->next == NULL) //空链表
{
head->next = pnew;
}
else //头插法加入链表
{
pnew->next = head->next;
head->next = pnew;
}
#endif
pnew->next = head->next;
head->next = pnew;
printf("是否继续?");
scanf("%c", &ch);
while(getchar()!='\n');
}
return ;
}
带头结点的链表查找,插入
//查找操作
struct node *list_search_by_num(struct node *head, int num)
{
struct node *p = head->next;
while(p!=NULL)
{
if(p->num == num)
{
return p;
}
p = p->next;
}
return p;
}
//插入操作: 插入到指定学号的前面
// ps:不管插入到什么位置,都是找插入位置的前一个节点
void list_insert_by_num(struct node *head, int num, struct node *pnew)
{
struct node *psearch = NULL;
psearch = list_search_by_num(head, num);
if(NULL == psearch)
{
printf("插入失败,学号%d不存在!\n", num);
return ;
}
struct node *p = head;
while(p->next != psearch)
{
p = p->next;
}
pnew->next = psearch;
p->next = pnew;
return ;
}
带头结点的链表删除
//删除操作:
//不管删除哪一个节点, 都是找前一个节点, 让前一个节点的next保存删除节点下一个节点的地址
void list_del_by_num(struct node *head, int num)
{
struct node *psearch = NULL;
psearch = list_search_by_num(head, num);
if(NULL == psearch)
{
printf("删除失败,学号%d不存在!\n", num);
return ;
}
struct node *p = head;
while(p->next != psearch)
{
p = p->next;
}
p->next = psearch->next;
free(psearch);
return ;
}
双向链表就是有一个指向后面的next指针,还有一个指向前面的pre指针,可以更加方便的进行增删改查等操作
双向链表的添加
void create_list(struct node *head)
{
struct node *pnew = NULL;
char ch;
printf("是否创建链表?");
scanf("%c", &ch);
while(getchar()!='\n');
while(ch=='Y'||ch=='y')
{
//1、创建新的节点,并且赋值
pnew = create_node();
printf("请输入学号:");
scanf("%d", &pnew->num);
while(getchar()!='\n');
printf("请输入姓名:");
scanf("%s", pnew->name);
while(getchar()!='\n');
//2、加入链表
if(head->next == NULL) //空链表
{
head->next = pnew;
pnew->pre = head;
}
else //非空链表,头插法
{
pnew->next = head->next;
head->next->pre = pnew;
head->next = pnew;
pnew->pre = head;
}
printf("是否继续?");
scanf("%c", &ch);
while(getchar()!='\n');
}
return ;
}
双向链表的查找