复习:
《大话数据结构》
1、什么是数据结构
专门研究数据之间关系和操作的学科,而非计算方法
数据结构+算法=程序
2、逻辑结构和物理结构
逻辑结构:
集合: 除了同属一个集合之外,数据之间没有任何关系
线性结构: 数据之间具有一对一的关系
树型结构: 数据之间具有一对多的关系
图型结构: 数据之间具有多对多的关系
物理结构:
顺序结构:数据存在连续的内存中,使用数据之间相对位置表示数据之间的关系
链式结构:数据存储在不确定位置的内存中,数据项中有一块指针域,用来表示数据之间的关系
3、线性表结构:
顺序表:数组
链式表:链表
常见的面试题:数组和链表的优缺点
4、功能受限的表结构
栈:只有一个出入口、先进后出
有四种顺序栈名称:
空增栈:
top初值:0 先入栈,再top++
空减栈:
top初值:cal-1 先入栈,再top--
满增栈:
top初值:-1 先top++,再入栈
满减栈:
top初值:cal 先top--,再入栈
队列:有两个出入口,队尾进,对头出,先进先出
封装链表:
1、单链表
之前的没封装过的单链表,尾添加效率低、非法位置的判断效率低
节点:
数据域
指针域
单链表结构:
头指针 (带头节点)
尾指针
节点数量
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define TYPE int
//封装带头节点的单链表
typedef struct Node
{
TYPE data;
struct Node* next;
}Node;
Node* creat_node(TYPE data)
{
Node* node= malloc(sizeof(Node));
node->next=NULL;
node->data=data;
return node;
}
typedef struct List
{
Node* head; //头指针
Node* tail; //尾指针
size_t size; //数量
}List;
//创建链表
List* creat_list(void)
{
List* list = malloc(sizeof(List));
list->head = creat_node(0); //带头节点
list->tail = NULL;
list->size = 0;
return list;
}
//头添加
void add_head_list(List* list,TYPE data)
{
Node* node = creat_node(data);
if(list->size == 0)
{
list->head->next= node;
list->tail = node;
}
else
{
node->next = list->head->next;
list->head->next = node;
}
list->size++;
}
//尾添加
void add_tail_list(List* list,TYPE data)
{
Node* node = creat_node(data);
if(0 == list->size)
{
list->head->next = node;
list->tail = node;
}
else
{
list->tail->next = node;
list->tail = node;
}
list->size++;
}
//头删除
bool del_head_list(List* list)
{
if(0 == list->size) return false;
Node* temp = list->head->next;
list->head->next = temp->next;
free(temp);
if(0 == list->size) list->tail == NULL;
return true;
}
//尾删除
bool del_tail_list(List* list)
{
if(0 == list->size) return false;
free(list->tail);
if(1 == list->size)
{
list->head->next=NULL;
list->tail = NULL;
}
else
{
Node* prev = list->head->next;
while(prev->next != list->tail) prev=prev->next;
prev->next = NULL;
list->tail = prev;
}
list->size--;
return true;
}
//插入
bool insert_list(List* list,size_t index,TYPE data)
{
if(index >= list->size) return false;
Node* node = creat_node(data);
Node* prev = list->head;
for(int i =0; i<index; i++)
{
prev = prev->next;
}
node->next = prev->next;
prev->next = node;
list->size++;
return true;
}
//按值删除
bool del_val_list(List* list,TYPE data)
{
if(0 == list->size) return false;
if(data == list->head->next->data) return del_head_list(list);
if(data == list->tail->data) return del_tail_list(list);
for(Node* n = list->head->next; n->next; n=n->next)
{
if(n->next->data == data)
{
Node* temp = n->next;
n->next = temp->next;
free(temp);
return true;
}
}
return false;
}
//按位置删除
bool del_index_list(List* list,size_t index)
{
if(index >= list->size) return false;
if(0 == index) return del_head_list(list);
if(list->size-1 == index) return del_tail_list(list);
Node* prev = list->head->next;
for(int i=1;i<index;i++)
{
prev=prev->next;
}
Node* node = prev->next;
prev->next= node->next;
free(node);
list->size--;
return true;
}
//按值修改
bool modify_val_list(List* list, TYPE old, TYPE val)
{
bool flag=false;
for(Node* n=list->head->next;n;n=n->next)
{
if(n->data==old)
{
n->data=val;
flag=true;
}
}
return flag;
}
//按位置修改
bool modify_index_list(List* list,int index,TYPE val)
{
if(index>=list->size) return false;
Node* n=list->head->next;
for(int i =0;i<index;i++)
{
n=n->next;
}
n->data = val;
return true;
}
//查询
int query_list(List* list ,TYPE val)
{
int i=0;
for(Node* n=list->head->next;n;n=n->next)
{
if(n->data == val)
{
return i;
}
else
{
i++;
}
}
return -1;
}
//访问
bool access_list(List* list,int index,TYPE* val)
{
if(index>=list->size) return false;
Node* n=list->head->next;
for(int i =0;i<index;i++)
{
n=n->next;
}
*val = n->data;
return true;
}
//排序
void sort_list(List* list)
{
for(Node* n1=list->head->next;n1->next!=NULL;n1=n1->next)
{
for(Node* n2=n1->next;n2!=NULL;n2=n2->next)
{
if(n1->data < n2->data)
{
TYPE temp=n1->data;
n1->data=n2->data;
n2->data=temp;
}
}
}
}
//遍历
void show_list(List* list)
{
for(Node* n=list->head->next; n; n=n->next)
{
printf("%d ",n->data);
}
printf("\n");
}
//清空
void clean_list(List* list)
{
//while(list->size) del_tail_list(list);
while(list->head->next)
{
Node* temp = list->head->next;
list->head->next = temp->next;
free(temp);
}
list->tail = NULL;
list->size = 0;
}
//销毁
void destroy_list(List* list)
{
clean_list(list);
free(list->head);
free(list);
}
int main(int argc,const char* argv[])
{
List* list=creat_list();
for(int i=0; i<10; i++)
{
add_tail_list(list,i+1);
}
show_list(list);
int i=query_list(list,10);
printf("%d\n",i);
int num=-10;
access_list(list,10,&num);
printf("%d\n",num);
show_list(list);
sort_list(list);
show_list(list);
}
2、静态链表
节点:
数据域
游标
静态链表的节点存储在连续的内存中,通过游标来访问下一个节点
这种链表没有指针域,需要在插入或删除时,通过修改游标的值完成,而不需要动态申请、释放内存,但是也可以实现链式的效果
但是它牺牲了随机访问的功能,而且也缺少真正链式表的全部优点
3、循环链表
让链表的最后一个节点的next不再指向NULL,而是指向头节点,这种链表统称为单向循环链表,简称循环链表,它的优点是可以通过任意节点遍历整个链表
4、双向循环链表
节点:
前驱指针
数据
后继指针
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define TYPE int
// 演示双向链表特点
typedef struct Node
{
struct Node* prev; //前驱
TYPE data;
struct Node* next; //后继
}Node;
Node* creat_node(TYPE data)
{
Node* node = malloc(sizeof(Node));
node->data = data;
node->prev =node;
node->next=node;
return node;
}
void _add_list(Node* n1,Node*n2,TYPE data)
{
Node* node = creat_node(data);
node->prev = n1;
node->next = n2;
n1->next = node;
n2->prev = node;
}
void _del_list(Node* node)
{
node->prev->next=node->next;
node->next->prev=node->prev;
free(node);
}
//头添加
void add_head_list(Node* head,TYPE data)
{
_add_list(head,head->next,data);
}
//尾添加
void add_tail_list(Node* head,TYPE data)
{
_add_list(head->prev,head,data);
}
//按位置删除
bool del_index_list(Node* head,int index)
{
Node* n=head->next;
for(int i=0;i<index;i++)
{
n=n->next;
if(n == head) return false;
}
_del_list(n);
return true;
}
//按值删除
bool del_val_list(Node* head,TYPE val)
{
for(Node* n=head->next;n!=head;n=n->next)
{
if(n->data==val)
{
_del_list(n);
return true;
}
}
return false;
}
//插入
bool insert_list(Node* head,size_t index,TYPE data)
{
Node* n=head->next;
for(int i=0;i<index;i++)
{
n=n->next;
if(n==head) return false;
}
_add_list(n->prev,n,data);
return true;
}
//遍历
void show_list(Node* head)
{
for(Node* n=head->next;n!=head;n=n->next)
{
printf("%d ",n->data);
}
printf("\n");
}
int main(int argc,const char* argv[])
{
Node* head=creat_node(0); //带头节点
for(int i =0;i<10;i++)
{
add_head_list(head,i+1);
}
show_list(head);
// insert_list(head,5,88);
// del_index_list(head,9);
del_val_list(head,5);
show_list(head);
}