总结
第一章:
数据结构包括:逻辑结构,储存结构, 运算集合
逻辑结构:分为线性(线性表, 栈, 队列, 字符串, 数组, 广义表)
非线性:树,图,网
储存结构:顺序储存和非顺序储存 线性储存,散列储存,链式储存
算法+数据结构 = 程序
第二章:线性表:
线性表的线性储存
逻辑结构:
除了端点以外,所有元素均有一个前驱和一个后继.具有一对一的关系.
存储结构:
一组地址连续的储存单元依次存储
#define MAX 100
typedef struct{
int elem[MAX];
int last;
}SeqList;
基本运算:
查找:
按照坐标查找和按照内容查找
插入:
判插入位置,判满-->找到位置,移动后面的元素-->插入!
删除:
参数:删除的位置序号
判位置-->将插入元素放到对应变量中-->移动元素
双非递减有序表合并:
元素比较插入-->单表剩余元素插入
2.3线性表的链式存储
单链表: 设头指针H指向第一个结点,前驱结点指针域存放下一个结点的地址
为了方便,在第一个结点之前设立头结点,头指针指向头结点,头结点的指针域存储指向第一个结点的指针
typedef struct Node{//Node为结构标记
char data;
struct Node *next;
}Node, *LinkList; //Node为类型定义
注意:Node*和LinkList同为结构指针, 两者等价.后者习惯指单链表头指针变量,前者定义单链表中结点指针
Attention!!!!!!!
初始化:
InitList(LinkList *L){
//该处为双指针, 返回值为空, 靠指针传出去!!!
*L = (LinkList)malloc(szieof(Node));
(*L)->next = NULL;
}
//L指向单链表头结点的指针,*L初始化单链表的头指针变量
建立单链表://头插法
void CreateFromHead(LinkList L){
Node *s;
char c;
int flag = 1;
while(flag){
c = getchar();
if(c != '$'){
s = (Node *)malloc(sizeof(Node));
s->data = c;
s->next = L->next;//L相当于头结点(表头指针)
L->next = s;
}
else
flag = 0;
}
}
//尾插法
void CreateFromTail(LinkList L){
Node *s, *r;
char c;
int flag = 1;
r = L;
while(flag){
c = getchar();
if(c != '$'){
s = (Node *)malloc(sizeof(Node));
s->data = c;
r->next = s;
r = s;
}
else{
flag = 0;
r->next = NULL;
}
}
}
查找:
按照序号和按照值,和线性表差不多,判空条件改为while(p)
求长度:...
单链表插入:
判断插入位置合理性-->插入(一般都是头插,类似语句如下:s->next = pre->next; pre->next = s)
删除:
关键语句:r = pre->next;//赋值
pre->next = r->next;
*e = r->data;
free(r);//!!!
合并两个有序单链表:
思想:不用新分配空间,直接比较数据修改指针,把其中的一个表头当作新表表头...
LinkList MergeList(LinkList LA, LinkList LB){
LinkList LC;
Node *pa, *pb, *r;
LC = LA;
pa = LA->next;
pb = LB->next;
r = LC;
while(pa && pb){
if(pa->data >= pb->data){
r->next = pa;
r = pa;
pa = pa->next;
}
else{
r->next = pb;
r = pb;
pb = pb->next;
}
}
if(pa)
r->next = pa;
else
r->next = pb;
r->next = NULL;
free(r);
free(LB);
return(LC); //return LC;
}
循环链表:将单链表最后一个结点指针域NULL改为指向表头结点
单循环链表判断条件: p != L或 p->next != NULL;
初始化循环单链表:
InitCLinkList(LinkList *CL){
*CL = (LinkList)malloc(sizeof(Node));
(*CL)->next = *CL;//注意CL是指针(地址), *CL为结点,(或者说结点指针, 就是一般的结点)!!!!!!!!!!!!
}
Attention!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
建立循环单链表:易错
void CreateCLinkList(LinkList CL){
//尾插法
Node *rear, *s;
char c;
rear = CL; //典型步骤
c = getchar();
while(c != '$'){
s = (Node *)malloc(sizeof(Node));
s->data = c;
rear->next = s;
rear = s;//典型
c = getchar();//!!别忘记了
}
rear->next = CL;//
}
循环单链表合并:
LinkList Merge(LinkList LA, LinkList LB){
Node *p, *q;//带头结点
p = LA;
q = LB;
while(p->next != LA) p = p->next;
while(q->next != LB) q = q->next;
p->next = LB->next;
q->next = LA;
free(LB);
return LA;
}
//稍难,带尾指针的带头结点循环内单链表合并算法
LinkList Merge_2(LinkList LA, LinkList LB){
//LA LB为尾指针,所以LA->next and LB->next 为头结点
Node *p;
p = LA->next;//p暂时保存LA头结点地址
LA->next = LB->next->next;//指向LB第一个结点
free(LB->next);
LB->next = p;
return LB;//返回新的循环链表的尾指针
}
LinkList Merge_2(LinkList A, LinkList B){
Node *q;
q = B->next;
B->next = A->next->next;
free(A->next);
A->next = q;
return A;
}
双向链表:
typedef struct DNode{
int data;
struct