- 1. 顺序表的存储
- 定义:把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构
- 方法:用一组地址连续的存储单元依次存储线性表的元素,通过数组来实现
- 特点:访问效率高:邻近存储;修改效率低:增加和删除需要移动大量数据节点
- 2. 顺序表的存储结构
-
<- length -> |
a0 |
a1 |
... |
ai |
|
|
|
|
|
|
<- MaxSize -> |
- 3. 顺序表的数据结构
-
//伪代码
#define MaxSize 20
typedef struct
{
elementType *data;
int len;
}List;
-
//实际代码
#define MaxSize 20
typedef struct
{
int *data;
int len;
}List;
- 4. 顺序表的基本操作
- 4.0 几点说明
- .函数的返回类型
- .异常的处理
- 4.1 初始化
- 创建一个总长度为MaxSize的空数组;
- 内存管理:如何申请空间??
- 参数传递:如何把地址传出来???
-
//[代码1]
int Init(List *list)
{
list->data = (int *)malloc(sizeof(int) * MaxSize);
if (list->data)
{
list->len = 0;
return 0;
}
else
{
return -1;
}
}
-
//[代码2]
int Init(List *list)
{
list->data = (int *)malloc(sizeof(int) * MaxSize);
if (!list->data)
{
return -1;
}
list->len = 0;
}
-
//[代码3]
int Init(List *list)
{
list->data = (int *)malloc(sizeof(int) * MaxSize);
if (list->data)
{
list->len = 0;
return 0;
}
return -1;
}
-
//[代码4]
int Init(List *list)
{
list->data = (int *)malloc(sizeof(int) * MaxSize);
return list->data ? list->len : -1;
}
-
//[代码5]
void Init(List *list)
{
list->data = (int *)malloc(sizeof(int) * MaxSize);
if (!list->data)
{
printf("init fail\n");
return;
}
list->len = 0;
printf("init ok\n");
}
- 4.2 赋值assign
- 为线性表的某个或某些元素赋值;
-
//利用数组名和地址偏移量赋值
*(list->data +i) = val;
//利用数组元素索引赋值
list->data[i] = val;
//利用数组对线性表整体赋值
void assign(List *list, int arr[], int len)
{
int i;
for (i = 0; i < len; i++)
{
list->data[i] = arr[i];
list->len++;
}
}
//利用输入scanf对线性表整体赋值
- 4.3 读getAt
- 根据位置/索引index取值el;
- 取到的值如何传递出去?
-
//赋值出去
void getAt(List *list, int ind, int *res)
{
if (ind < 0 || ind > list->len - 1)
{
printf("get-index overfollow.\n");
return;
}
*res = list->data[ind];
}
//return出去
int getAt(List *list, int ind)
{
if (ind < 0 || ind > list->len - 1)
{
return -1;
}
return list->data[ind];
}
- 4.4 插入insertAt
- 在线性表某个位置插入元素;
- 头插?尾插?
-
void insertAt(List *list, int ind, int el)
{
if (ind < 0 || ind > list->len || ind > MaxSize)
{
printf("insert-index overfollow\n");
return;
}
int i;
for (i = list->len; i > ind; i--)
{
list->data[i] = list->data[i - 1];
}
list->data[ind] = el;
list->len++;
}
- 4.5 删除delAt
- 删除线性表的元素;
- 需不需要返回被删除的元素?
-
void delAt(List *list, int ind, int *el)
{
if (ind < 0 || ind > list->len)
{
printf("del-index overfollow\n");
return;
}
*el = list->data[ind];
int i;
for (i = ind; i < list->len; i++)
{
list->data[i - 1] = list->data[i];
}
list->len--;
}
- [思考]删除前和删除后,最后一个元素有什么变化?
- 4.6 输出
- 显示/遍历线性表的元素;
- 如何个性化?
- 如何更直观?
-
void tranverse(List *list)
{
int i;
for (i = 0; i < list->len; i++)
{
printf("%d\t", list->data[i]);
}
}
void tranverse(List *list)
{
int i;
for (i = 0; i < list->len; i++)
{
printf("%d\t", i);
}
printf("\n");
for (i = 0; i < list->len; i++)
{
printf("%d\t", list->data[i]);
}
printf("\n");
printf("-----------------------\n");
}
- 5. 顺序表参考代码
-
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 5
typedef struct
{
int *data;
int len;
} List;
void Init(List *list)
{
list->data = (int *)malloc(sizeof(int) * MaxSize);
if (!list->data)
{
printf("init fail\n");
return;
}
list->len = 0;
printf("init ok\n");
}
void assign(List *list, int arr[], int len)
{
int i;
for (i = 0; i < len; i++)
{
list->data[i] = arr[i];
list->len++;
}
}
void tranverse(List *list)
{
int i;
for (i = 0; i < list->len; i++)
{
printf("%d\t", i);
}
printf("\n");
for (i = 0; i < list->len; i++)
{
printf("%d\t", list->data[i]);
}
printf("\n");
printf("--------------------------------------------------\n");
}
void getAt(List *list, int ind, int *res)
{
if (ind < 0 || ind > list->len - 1)
{
printf("get-index overfollow.\n");
return;
}
*res = list->data[ind];
}
void insertAt(List *list, int ind, int el)
{
if (ind < 0 || ind > list->len || ind > MaxSize)
{
printf("insert-index overfollow\n");
return;
}
int i;
for (i = list->len; i > ind; i--)
{
list->data[i] = list->data[i - 1];
}
list->data[ind] = el;
list->len++;
}
void delAt(List *list, int ind, int *el)
{
if (ind < 0 || ind > list->len)
{
printf("del-index overfollow\n");
return;
}
*el = list->data[ind];
int i;
for (i = ind; i < list->len; i++)
{
list->data[i - 1] = list->data[i];
}
list->len--;
}
int main(int argc, char *argv[])
{
int i, res;
List list;
Init(&list);
int val[10] = {10, 23, 4, 56, 26};
assign(&list, val, 5);
tranverse(&list);
getAt(&list, 3, &res);
insertAt(&list, 2, 11);
tranverse(&list);
delAt(&list, 2, &res);
tranverse(&list);
return 0;
}
- [Section End]
- 1. 链式表的存储
- . 逻辑上相邻;存储上随意
- . 存取效率低:只能通过头指针进入链表,根据每个结点的指针域访问其它结点:顺藤摸瓜/顺序存取法
- . 修改效率高:节点增加、删除操作,只需要修改链接指针,不必移动数据
- . 头指针:链表由头指针唯一确定; 不要弄丢头指针; 不要掉链子
- . 存储密度小
- 2. 链式表的存储结构
- . 除了数据元素外,借助指针实现数据之间的逻辑关系
- . 根据指针的多少和指向,可以细分:单链表、双向链表、循环链表等
-
-
- . 带头节点的单链表:为方便操作,通常在数据节点之前增加一个头节点,用来表示该链表;链表由指向头节点的头指针唯一确定
- . 节点分类:头节点、数据节点[首节点、尾节点]
-
- 3. 单链表的数据结构
-
//节点和链表共享一个数据结构
typedef struct LNode
{
int data;
struct LNode *next;
} Node, List;
//节点和链表单独定义数据结构
typedef struct node
{
int data;
struct node *next;
} Node;
typedef struct
{
Node *head;
int n;
} LinkList;
- 4. 单链表的基本操作
- 4.1 初始化Init
- 创建一个带有头节点的空链表;
-
Node *Init() {
Node *head=(Node *)malloc(sizeof(Node));
printf("%p\n",head);
head->next=NULL;
return head;
}
Status Init(List *list)
{
*list = (List *)malloc(sizeof(Node));
printf("insider %p\n", *list);
if (!(*list))
{
return ERROR;
}
(*list)->next = NULL;
return OK;
}
- 4.2 遍历Display
- 遍历链表,个性化输出每个节点数据;
-
void Display(List *list) {
Node *head=list->next;
while(head) {
printf("%d\t",head->data);
head=head->next;
}
printf("\n");
}
void Display(List *list){
printf("List->");
Node *head=list->next;
while(head){
printf("%d->",head->data);
head=head->next;
}
printf("NULL\n");
}
- 4.3 插入Insert
- 头插:在链表头部插入数据节点;
-
void InsertHead(List *list,int data) {
Node *p=list;
Node *node=(Node *)malloc(sizeof(Node));
node->data=data;
node->next=p->next;
list->next=node;
}
-
- 尾插:在链表尾部部插入数据节点;
-
void InsertTail(List *list,int data){
Node *p=list->next;
while(p->next){
p=p->next;
}
Node *node=(Node *)malloc(sizeof(Node));
node->data=data;
node->next=NULL;
p->next=node;
}
-
- 在链表指定位置插入数据节点;
-
void InsertByIndex(List *list, int ind, int data)
{
int i = 0;
List *p = list;
if (ind < 0 || ind > Len(list) - 1)
{
printf("index overfollow\n");
return;
}
while ( i < ind)
{
p = p->next;
i++;
}
Node *node = (List *)malloc(sizeof(Node));
node->data = data;
node->next = p->next;
p->next = node;
}
-
- []
- . 获取插入位置的前一个位置;
- . 头插、尾插是插入的特例;
- 4.4 表长Len
- 获取链表数据节点的个数;
-
int Len(List *list) {
int len=0;
Node *p=list->next;
while(p) {
len++;
p=p->next;
}
return len;
}
- 4.5 获取元素Get
- 根据指定位置获取链表数据节点;
-
void Get(List *list,int ind,int *res) {
int i=0;
int length=Len(list);
if( ind<0 || ind>length-1 ) {
printf("index overfollow\n");
return;
}
Node *p=list->next;
while(inext;
i++;
}
*res=p->data;
}
- 4.6 元素索引IndexOf
- 获取数据节点在链表中的位置;
-
int IndexOf(List *list, int data)
{
int i = 0;
Node *p = list->next;
while (p && p->data != data)
{
p = p->next;
i++;
}
return p?i:-1;
}
- 4.7 删除Delete
- 根据指定位置删除链表中的数据节点;
-
void DeleteByIndex(List *list, int ind, int *res)
{
int i = 0;
Node *p = list,*q;
if (ind < 0 || ind>Len(list)-1)
{
printf("index overfollow\n");
return;
}
while (p->next && i < ind)
{
printf("%d\t",i);
p = p->next;
i++;
}
q = p->next;
*res = q->data;
p->next = q->next;
free(q);
}
- []
- 1. 为什么要使用2个指针?
- 2. 如何删除指定元素?
- 3. 如何利用IndexOf函数删除指定元素?
- []
- free()的节点必须通过malloc()申请的节点;即:如果节点是手动创建的,则无法free(),会导致函数结束异常;
- 4.9 其它函数
- 根据业务需要,封装其它功能函数;
- 5. 单链表参考代码
-
//头文件
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *next;
} Node, List;
int Len(List *list);
Node *Init()
{
Node *head = (Node *)malloc(sizeof(Node));
printf("%p\n", head);
head->next = NULL;
return head;
}
void Display(List *list)
{
printf("List->");
Node *head = list->next;
while (head)
{
printf("%d->", head->data);
head = head->next;
}
printf("NULL\n");
}
void InsertHead(List *list, int data)
{
Node *p = list;
Node *node = (Node *)malloc(sizeof(Node));
node->data = data;
node->next = p->next;
p->next = node;
}
void InsertTail(List *list, int data)
{
Node *p = list;
while (p->next)
{
p = p->next;
}
Node *node = (Node *)malloc(sizeof(Node));
node->data = data;
node->next = NULL;
p->next = node;
}
void InsertByIndex(List *list, int ind, int data)
{
int i = 0;
List *p = list;
if (ind < 0 || ind > Len(list) - 1)
{
printf("index overfollow\n");
return;
}
while (i < ind)
{
p = p->next;
i++;
}
Node *node = (List *)malloc(sizeof(Node));
node->data = data;
node->next = p->next;
p->next = node;
}
int Len(List *list)
{
int len = 0;
Node *head = list->next;
while (head)
{
len++;
head = head->next;
}
return len;
}
void Get(List *list, int ind, int *res)
{
int i = 0;
int length = Len(list);
if (ind < 0 || ind > length - 1)
{
printf("index overfollow\n");
return;
}
Node *p = list->next;
while (i < ind)
{
p = p->next;
i++;
}
*res = p->data;
}
int IndexOf(List *list, int data)
{
int i = 0;
Node *p = list->next;
while (p && p->data != data)
{
p = p->next;
i++;
}
return p ? i : -1;
}
void DeleteByIndex(List *list, int ind, int *res)
{
int i = 0;
int length = Len(list);
Node *p = list;
Node *q = NULL;
if (ind < 0 || ind > length - 1)
{
printf("index overfollow\n");
return;
}
while (p->next && i < ind)
{
printf("%d\t", i);
p = p->next;
i++;
}
q = p->next;
*res = q->data;
p->next = q->next;
free(q);
}
//主文件
#include <stdio.h>
#include <stdlib.h>
#include "demo.h"
int Len(List *list);
int main(int argc, char *argv[])
{
int res,tmp;
List *list = Init();
InsertHead(list, 10);
InsertHead(list, 20);
InsertHead(list, 30);
Display(list);
res = Len(list);
printf("len=%d\n", res);
Get(list, 5, &res);
printf("get res=%d\n", res);
Display(list);
InsertTail(list, 190);
InsertTail(list, 180);
InsertTail(list, 170);
// InsertHead(list,10);
InsertByIndex(list, 2, 222);
Display(list);
InsertByIndex(list, 5, 222);
Display(list);
tmp = 222;
res = IndexOf(list, tmp);
printf("index of %d is %d\n", tmp, res);
tmp = 8;
res = IndexOf(list, tmp);
printf("index of %d is %d\n", tmp, res);
tmp = 7;
DeleteByIndex(list, tmp, &res);
printf("delete index of %d \n", res);
Display(list);
return 0;
}
- [Section End]
- 1. 通信录
- 项目效果请参照 通信录
- 参考代码;contact.h为定义的数据结构,请参照前面的数据结构和算法,根据实际情况灵活调整;
-
#include <stdio.h>
#include <stdlib.h>
#include "contact.h"
void menu(void);
int main(void)
{
int option, len;
printf("\nWelcome\n");
Contact *contact = Init();
do
{
menu();
printf("Please make a choice->>>");
scanf("%d", &option);
switch (option)
{
case Add:
AddByHead(contact);
break;
case Delete:
DeleteByIndex(contact);
break;
case Update:
UpdateByIndex(contact);
break;
case Search:
SearchByName(contact);
break;
case Print:
Display(contact);
break;
case Sort:
SortByAge(contact);
break;
case Output:
OutputToFile(contact);
break;
case LengthOfContact:
len = Length(contact);
printf("lenght of current contact is %d\n", len);
printf("%s %s\n\n", __TIME__, __DATE__);
break;
case AddByTail:
OutputToFile(contact);
break;
case Exit:
printf("Bye Bye\n");
printf("%s %s\n\n", __TIME__, __DATE__);
exit(0);
break;
default:
printf("Bye Bye\n");
printf("%s %s\n\n", __TIME__, __DATE__);
exit(0);
break;
}
} while (1);
return 0;
}
void menu(void)
{
printf("**********************************************\n");
printf("*** 1.Insert 2.Delete ***\n");
printf("*** 3.Update 4.Search ***\n");
printf("*** 5.Display 6.Sort ***\n");
printf("*** 7.Output 8.Length ***\n");
printf("*** 9.InsertByTail 0.Exit ***\n");
printf("**********************************************\n");
printf("<<<<<<<<<<<<<202012000001张树彬>>>>>>>>>>>>>\n\n");
}
- 2. 多项式加法
-
#include <stdio.h>
#include <stdlib.h>
typedef struct pNode
{
int coef;
int exp;
struct pNode *next;
} pNode;
typedef struct
{
struct pNode *head;
} PolyExp;
void createPlyExp(PolyExp *pe)
{
pe->head = (pNode *)malloc(sizeof(pNode));
pe->head->exp = -1;
pe->head->next = NULL;
pNode *pn, *pre, *p;
while (1)
{
pn = (pNode *)malloc(sizeof(pNode));
printf("conf:\n");
scanf("%d", &pn->coef);
printf("exp:\n");
scanf("%d", &pn->exp);
if (pn->exp < 0)
{
break;
}
pre = pe->head;
p = pre->next;
// 已有数据大于新数据,后移
while (p && p->exp > pn->exp)
{
pre = p;
p = p->next;
}
pn->next = p;
pre->next = pn;
}
}
void displayPolyExp(PolyExp *pe)
{
pNode *pn;
pn = pe->head->next;
while (pn)
{
printf("%dx^%d ", pn->coef, pn->exp);
pn = pn->next;
}
printf("\n");
}
void addPolyExp(PolyExp *pe0, PolyExp *pe1)
{
pNode *pre0 = pe0->head;
pNode *p0 = pe0->head->next;
pNode *pre1 = pe1->head;
pNode *p1 = pe1->head->next;
pNode *tmp;
while (p0 && p1)
{
while (p1)
{
if (p1->exp > p0->exp)
{
printf(">\n");
// p1不掉链
pre1->next = p1->next;
// 移动p1的节点到p0里
p1->next = p0;
pre0->next = p1;
p1 = pre1->next;
// 因为p0加入了一个节点,所以要更新p0的指针域:p0不用动,pre0前移一个节点
pre0 = pre0->next;
}
else if (p1->exp == p0->exp)
{
printf("=\n");
// 系数相加
p0->coef = p0->coef + p1->coef;
// p1不掉链
pre1->next = p1->next;
tmp = p1;
// 释放空间
free(tmp);
p1 = pre1->next;
}
else if (p1->exp < p0->exp)
{
printf("<\n");
break;
}
}
pre0 = p0;
p0 = p0->next;
}
}
int main()
{
PolyExp *pe0, *pe1;
pe0 = (PolyExp *)malloc(sizeof(PolyExp));
pe1 = (PolyExp *)malloc(sizeof(PolyExp));
createPlyExp(pe0);
displayPolyExp(pe0);
createPlyExp(pe1);
displayPolyExp(pe1);
addPolyExp(pe0, pe1);
printf("res\n");
displayPolyExp(pe0);
return 0;
}
- [Section End]